System V信号量与System V其他两种通信机制(消息队列、共享内存)不同,其用来实现同步、互斥进程动作,通过semget函数创建一个信号集或打开一个信号量集,信号集又包括多个信号量,信号量的值要大于等于0,小于0,就会阻塞。
信号量pv操作:p操作:操作当前信号量减去某个值
v操作:操作当前信号量加上某个值
int semget(key_t key, int nsems, int semflg)
1 . key : IPC key
2 .nsems : 信号量个数
3 . semgflg : 信号量集权限
int semctl(int semid, int semnum, int cmd, union semun arg)
1 .semid:为信号量集标识符
2.semnum:为第几个信号量
3 .cmd:为以下取值:
4 .union semun arg : 为以下取值:
union semun
{
int val;
strut semid* buf;
unsigned short* array;
};
三 . semop函数:
int semop(int semid, struct sembuf sops, size_t nsops)
1. semid:为信号量集标识符
2. sembuf *sops(可以为结构体数组首地址):为以下取值:
struct sembuf
{
unsigned short sem_num;
short sem_op;
short sem_flg;
};
3. nsops:sembuf *sops个数
#include
#include
#include
#include
#include
int main()
{
int pid;
int count = 0;
pid = fork();
if(pid > 0)
{
while(count < 1000)
{
count++;
printf("父进程:%d\n",count);
}
wait(NULL); //等待子进程退出
}
else if(pid == 0)
{
while(count < 1000)
{
count++;
printf("子进程:%d\n",count);
}
}
else if(pid < 0)
{
printf("fork error\n");
exit(1);
}
return 0;
}
父进程创建出子进程,俩进程各计数到1000,并打印出来,由于未使用信号量实现俩进程互斥,所以父子进程会交替打印。
#include
#include
#include
#include
#include
#include
#include
#include
struct sembuf add_sop,cut_sop;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
void add_init()
{
add_sop.sem_num = 0;
add_sop.sem_op = 1; //p操作
add_sop.sem_flg = 0;
}
void cut_init()
{
cut_sop.sem_num = 0;
cut_sop.sem_op = -1; //v操作
add_sop.sem_flg = 0;
}
int main()
{
int count = 0;;
int semid;
union semun arg;
int pid;
arg.val = 1;
add_init();
cut_init();
semid = semget(IPC_PRIVATE,1,IPC_CREAT | S_IRUSR | S_IWUSR); //信号量个数为1
semctl(semid,0,SETVAL,arg); //设置信号量0的值为1
pid = fork();
if(pid > 0) // 父进程
{
semop(semid,&cut_sop,1); // 信号量p操作
while(count < 1000)
{
count++;
printf("父进程:%d\n",count);
}
semop(semid,&add_sop,1); // 信号量v操作
wait(NULL); //等待子进程退出
}
else if(pid == 0) //子进程
{
semop(semid,&cut_sop,1); // 信号量p操作
while(count < 1000)
{
count++;
printf("子进程:%d\n",count);
}
semop(semid,&add_sop,1); // 信号量v操作
}
else if(pid < 0)
{
printf("fork error\n");
exit(1);
}
return 0;
}
加入信号量后,俩进程能够实现互斥。一个进程在计数打印,另一个进程p操作就会使信号量小于0,进而阻塞,必须要等待上一个进程计数打印完成后,进行v操作释放信号量,才会解除阻塞。