信號量集函數
查看創建的信號量:ipcs -s
刪除創建的信號量:ipcrm -S key
1.創建信號量集
semget函數:
int semget(key_t key, //id
int nsems,//信號量集中有幾個信號量 打開寫0
int semflg);//IPC_CREAT|0644 打開0
代碼實現爲:
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/ipc.h>
5 #include <sys/sem.h>
6 #include <unistd.h>
7
8 //創建信號量集
9
10 int main()
11 {
12 int id=semget(1234,1,IPC_CREAT|0644);
13 if(id==-1)
14 perror("semget"),exit(1);
15
16 printf("create ok!\n");
17 }
2.設置初值
semctl函數:
union semun {
int val; /* Value for SETVAL */
};
int semctl(int semid, //id
int semnum,//給第幾個信號量的賦值
int cmd,//SETVAL
...);
返回值:當前信號量的值
代碼實現爲:
setval.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/ipc.h>
4 #include <sys/sem.h>
5 #include <stdlib.h>
6
7
8 union semun
9 {
10 int val;
11 };
12
13 int main()
14 {
15 int id=semget(1234,0,0);//打開信號量集填0
16 if(id==-1)
17 perror("semget"),exit(1);
18
19 union semun su;//聯合體變量
20 su.val=10;
21 semctl(id,0,SETVAL,su);//設置初值
22 }
3.獲得信號量的值
int semctl(int semid, //id
int semnum,//想獲得第幾個信號量的值
int cmd);//GETVAL
返回值:當前信號量的值
getval.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/ipc.h>
4 #include <sys/sem.h>
5
6 int main(void)
7 {
8 int id=semget(1234,0,0);
9 if(id==-1)
10 perror("semget"),exit(1);
11 int ret=semctl(id,0,GETVAL);//獲取第幾個信號量的初值
12 printf("val=%d\n",ret);
13 }
2與3結果如下:
4.PV操作
semop函數:
struct sembuf{
unsigned short sem_num;/* semaphore number */ 信號量集第幾個信號量的下標
short sem_op; /* semaphore operation */ -1 1 pv操作的值
short sem_flg; /* operation flags */ 0
}
int semop(int semid,//id
struct sembuf sops[] , //數組
unsigned nsops); //數組元素個數
代碼實現爲:
//循環打印o,x
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/sem.h>
5 #include <sys/ipc.h>
6 #include <unistd.h>
7
8 //printox
9
10 int id;
11 union semun
12 {
13 int val;
14 };
15
16
17 void p()
18 {
19
20 struct sembuf sb[1];//創建結構體數組
21 sb[0].sem_num=0;//信號量集中第幾個信號量的下標
22 sb[0].sem_op=-1;//p操作
23 sb[0].sem_flg=0;
24 semop(id,sb,1);//進行pv操作
25 }
26 void v()
27 {
28
29 struct sembuf sb[1];//創建結構體數組
30 sb[0].sem_num=0;//信號量集中第幾個信號量的下標
31 sb[0].sem_op=1;//v操作
32 sb[0].sem_flg=0;
33 semop(id,sb,1);//進行pv操作
34 }
35 void printox(char c)
36 {
37 int i;
38
39 for(i=0;i<10;i++)
40 {
41 p();//保證打印ox交叉執行
42 printf("%c",c);
43 fflush(stdout);
44 sleep(rand()%3);
45
46 printf("%c",c);
47 fflush(stdout);
48 sleep(rand()%2);
49 v();
50 }
51
52 }
53
54
55 int main(void)
56 {
57 srand(getpid());//隨機
58 int id=semget(1235,1,IPC_CREAT|0644);//創建信號量集
59
60 union semun su={1};
61 semctl(id,0,SETVAL,su);
62
63 //創建子進程
64 pid_t pid=fork();
65 if(pid==0)
66 {
67 printox('O');
68 }
運行結果爲:
信號量實現哲學家就餐模型(有驚喜哦)
1 #include <iostream>
2 using namespace std;
3 #include <stdio.h>
4 #include <sys/ipc.h>
5 #include <sys/sem.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9
10 int id;
11 union semun
12 {
13 int val;
14 };
15
16 //p
17 void take2fork(int num)
18 {
19 struct sembuf sb[2]={{num,-1,0},{(num+1)%5,-1,0}};
20 semop(id,sb,2);
21 }
22
23 void put2fork(int num)
24 {
25 struct sembuf sb[2]={{num,1,0},{(num+1)%5,1,0}};
26 semop(id,sb,2);
27 }
28
29 void zxj(int num)
30 {
31 while(1)
32 {
33 printf("%d思考 \n",num);
34 sleep(rand()%3);
35 printf("%d我餓了\n",num);
36 take2fork(num);
37 printf("%d開吃\n",num);
38 sleep(rand()%3);
39 printf("%d好飽\n",num);
40 put2fork(num);
41 }
42
43 }
44
45 int main()
46 {
47 srand(getpid());
48 id=semget(1235,5,IPC_CREAT|0644);
49
50 if(id==-1)
51 perror("semget"),exit(1);
52
53 union semun su={1};
54
55 for(int i=0;i<5;i++)
56 {
57 //設置初值
58 semctl(id,i,SETVAL,su);
59 }
60
61 int num=0;
62 for(int i=1;i<5;i++)
63 {
64 pid_t pid=fork();
65 if(pid==0)
66 {
67 num=i;
68 break;
69 }
70 }
71
72 zxj(num);
73 }
模型圖爲:
運行結果如下:
避免了死鎖的產生!