信号量集函数
查看创建的信号量: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 }
模型图为:
运行结果如下:
避免了死锁的产生!