今天我们学习了进程间痛讯的几种主要方式:
##管道(pipe)和有名管道(FIFO)
##信号(signal)
##消息队列
##共享内存(semaphore)
##信号量(spcket)
运用二值信号与共享内存的进程间通讯代码如下
shm1.c:
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#define SHMKEY 1234
#define SHMSIZE 4096
#define SEMKEY 1234
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux specific) */
};
void sem_p(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = -1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror("semop");
}
}
void sem_v(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = 1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror("semop");
}
}
int main()
{
int shmid;
int ret;
void *shmadder;
int count = 100;
shmid = shmget(SHMKEY,SHMSIZE,IPC_CREAT | IPC_EXCL);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
int semid = semget(SEMKEY, 1, IPC_CREAT | IPC_EXCL); //创建信号量(1个)
if (-1 == semid)
{
perror("semget");
exit(1);
}
union semun s;
s.val = 1; //二值信号量
ret = semctl(semid, 0, SETVAL, s); //初始化信号量
if (-1 == ret)
{
perror("semctl");
exit(1);
}
shmadder = shmat(shmid,NULL,0);
if(NULL == shmadder)
{
perror("shmat");
exit(1);
}
*(int *)shmadder = count;
while(1)
{
sem_p(semid); //减一操作
count = *(int *)shmadder;
if(count < 0)
{
break;
}
printf("%d count = %d\n",getpid(),count);
count--;
usleep(10000);
*(int *)shmadder = count;
sem_v(semid); //加一操作
}
shmdt(shmadder);
sleep(1);
shmctl(shmid, IPC_RMID, NULL); //删除共享内存
semctl(semid, 0, IPC_RMID); //删除信号量
return 0;
}
shm2.c:
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#define SHMKEY 1234
#define SHMSIZE 4096
#define SEMKEY 1234
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux specific) */
};
void sem_p(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = -1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror("semop");
}
}
void sem_v(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = 1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror("semop");
}
}
int main()
{
int shmid;
int ret;
void *shmadder;
int count = 100;
shmid = shmget(SHMKEY,SHMSIZE,0);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
int semid = semget(SEMKEY, 1, 0); //获取信号量(1个)
if (-1 == semid)
{
perror("semget");
exit(1);
}
shmadder = shmat(shmid,NULL,0);
if(NULL == shmadder)
{
perror("shmat");
exit(1);
}
while(1)
{
sem_p(semid); //减一操作
count = *(int *)shmadder;
if(count < 0)
{
break;
}
printf("%d count = %d\n",getpid(),count);
count--;
usleep(10000);
*(int *)shmadder = count;
sem_v(semid); //加一操作
}
shmdt(shmadder);
return 0;
}