System V信號量:
System V信號量與System V其他兩種通信機制(消息隊列、共享內存)不同,其用來實現同步、互斥進程動作,通過semget函數創建一個信號集或打開一個信號量集,信號集又包括多個信號量,信號量的值要大於等於0,小於0,就會阻塞。
信號量pv操作:
p操作:操作當前信號量減去某個值
v操作:操作當前信號量加上某個值
一 . semget函數(創建信號量集):
int semget(key_t key, int nsems, int semflg)
1 . key : IPC key
2 .nsems : 信號量個數
3 . semgflg : 信號量集權限
二 . semctl函數(信號量控制):
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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
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 <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
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操作
cut_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操作釋放信號量,纔會解除阻塞。