#ifndef __SEM
2 #define __SEM
3
4 //声明一个创>
5 int init_sem(
6
7 //声明一个p操
8 int P(int sem
9
10 //声明一个v操
11 int W(int sem
12
13 //声明一个删>
14 int del_sem(i
15
16 #endif
1 #include <myhead.h>
2 union semun {
3 int val; /* Value for SETVAL */
4 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
5 unsigned short *array; /* Array for GETALL, SETALL */
6 struct seminfo *__buf; /* Buffer for IPC_INFO
7 (Linux-specific) */
8 };
9 //信号灯集里每个信号灯的初始化
10 int sem_value(int semid,int semno,int semvalue)
11 {
12 union semun us;
13 us.val=semvalue;
14 if(semctl(semid,semno,SETVAL,us)==-1)
15 {
16 perror("semctr");
17 return -1;
18 }
19 return 0;
20 }
21 //创建信号灯集并初始化函数
22 int init_sem(int semnum)
23 {
24 //1.创建一个key钥匙
25 key_t key;
26 if((key=ftok("/",'t'))==-1)
27 {
28 perror("ftok");
29 return -1;
30 }
31 //2.创建一个信号灯集
32 int semid;
33 if((semid=semget(key,semnum,IPC_CREAT|IPC_EXCL|0664))==-1)
34 {
35 if(errno==EEXIST)
36 {
37 //防止多进程同时调用时多次初始化
38 semid=semget(key,semnum,IPC_CREAT|0664);
39 return semid;
40 }
41 perror("semget");
42 return -1;
43 }
44 //3.信号灯集初始化
45 for(int i=0;i<semnum;i++)
46 {
47 if(i==0)
48 {
49 //参数1:id
50 //参数2:初始化的信号灯编号
51 //参数3:初始化的信号灯的value值
52 sem_value(semid,i,1);
53 }
54 else
55 {
56 sem_value(semid,i,0);
57 }
58 }
59 return semid;
60 }
61
62 //p操作函数
63 int P(int semid,int semno)
64 {
65 struct sembuf buf;
66 buf.sem_num=semno;//灯集里灯编号
67 buf.sem_op=1; //释放资源
68 buf.sem_flg=0; //阻塞
69 if(semop(semid,&buf,1)==-1)
70 {
71 perror("semop");
72 return -1;
73 }
74 return 0;
75
76 }
77 //w操作函数
78 int W(int semid,int semno)
79 {
80 struct sembuf buf;
81 buf.sem_num=semno;//灯集里灯编号
82 buf.sem_op=-1; //申请资源
83 buf.sem_flg=0; //阻塞
84 if(semop(semid,&buf,1)==-1)
85 {
86 perror("semop");
87 return -1;
88 }
89 return 0;
90 }
91
92 //删除信号灯的函数
93 int del_sem(int semid)
94 {
95 if(semctl(semid,0,IPC_RMID,0)==-1)
96 {
97 perror("semctl");
98 return -1;
99 }
100 return 0;
101 }
1 #include <myhead.h>
2 #include "sem.h"
3 int main(int argc, const char *argv[])
4 {
5 //创建钥匙
6 key_t key=-1;
7 if((key=ftok("/",'c'))==-1)
8 {
9 perror("ftok");
10 return -1;
11 }
12 //创建共享享内存
13 int shmid;
14 if((shmid=shmget(key,4096,IPC_CREAT|0664))=
15 {
16 perror("shmget");
17 return -1;
18 }
19 //映射到用户空间
20 char *adder;
21 if((adder=shmat(shmid,NULL,0))==(void *)-1)
22 {
23 perror("shmat");
24 return -1;
25 }
26 //创建一个信号灯集
27 int semid;
28 semid=init_sem(4);
29 //创建父子进程
30 pid_t pid;
31 pid=fork();
32 if(pid<0)
33 {
34 perror("fork");
35 return -1;
36 }
37 else if(pid>0)
38 {
39 //父进程
40 while(1)
41 {
42 //等待0信号资源
43 W(semid,0);
44 fgets(adder,4096,stdin);
45 adder[strlen(adder)-1]='\0';
46 //释放1信号资源
47 P(semid,1);
48 if(strcmp(adder,"quit")==0)
49 {
50 break;
51 }
52 }
53 wait(NULL);
54 }
55 else
56 {
57 //子进程
58 while(1)
59 {
60 //等待3信号资源
61 W(semid,3);
62 //房子里面拿东西
63 printf("共享内存数据:%s\n",adder);
64 //释放2信号资源
65 P(semid,2);
66 if(strcmp(adder,"quit")==0)
67 {
68 break;
69 }
70 }
71 exit(EXIT_SUCCESS);
72 }
73 //取消链接
74 shmdt(adder);
75 return 0;
76 }