1 #include<sys/types.h>
2 #include<sys/ipc.h>
3 #include<sys/sem.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include<errno.h>
7
8 int gSemid = 0;
9 typedef int sem_t;
10 #define ERR_EXIT(m) \
11 do \
12 { \
13 perror(m); \
14 exit(EXIT_FAILURE); \
15 }while(0)
16
17 sem_t CreateSem(key_t key, int value)
18 {
19 union semun sem;
20 sem_t semid;
21 sem.val = value;
22
23 semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);//创建信号量个数为1
24 if(-1 == semid)
25 {
26 ERR_EXIT("semget");
27 }
28 semctl(semid, 0, SETVAL, sem);//参数2-要操作的信号量在信号量集中的编号;参数3-cmd...
29
30 return semid;
31 }
32
33 int Sem_P(sem_t semid)
34 {
35 //sops有三种方式,0-默认阻塞、IPC_NOWAIT-非阻塞、SEM_UNDO-撤销上一次操作
36 struct sembuf sops={0,-1,0};
37 return (semop(semid,&sops,1));
38 }
39
40 int Sem_V(sem_t semid)
41 {
42 struct sembuf sops={0,+1,0};
43 return (semop(semid,&sops,1));
44 }
45
46 void SetvalueSem(sem_t semid, int value)
47 {
48 union semun sem;
49 sem.val = value;
50
51 semctl(semid,0,SETVAL,sem);
52 }
53
54 int GetvalueSem(sem_t semid)
55 {
56 union semun sem;
57 return semctl(semid,0,GETVAL,sem);
58 }
59
60 void DestroySem(sem_t semid)
61 {
62 union semun sem;
63 sem.val = 0;
64 semctl(semid,0,IPC_RMID,sem);
65 }
66
67 void Print(char opChar)
68 {
69 int pauseTime;
70 srand(getpid());
71 int i;
72
73 for(i=0; i<10; i++)
74 {
75 if(Sem_P(gSemid) != 0)
76 ERR_EXIT("Sem_P");
77 //临界区-begin
78 printf("%c", opChar);
79 fflush(stdout);
80 pauseTime = rand()%3;
81 sleep(pauseTime);
82 printf("%c", opChar);
83 fflush(stdout);
84 //临界区-end
85 Sem_V(gSemid);
86 pauseTime = rand()%2;
87 sleep(pauseTime);
88 }
89 }
90
91 int main(void)
92 {
93 char i;
94 key_t key;
95 int value = 0;
96 int pid;
97
98 key = ftok("./ipc", 'c');
99 gSemid = CreateSem(key,1);
100
101 value = GetvalueSem(gSemid);
102 printf("信号量值 = %d\n",value);
103
104 pid = fork();
105 if(-1 == pid)
106 {
107 ERR_EXIT("fork");
108 }
109
110 if(pid > 0)//父进程
111 {
112 Print('o');
113 wait(NULL);//等待子进程推出,删除信号量集
114 DestroySem(gSemid);
115 }else//子进程
116 {
117 Print('x');
118 }
119
120 #if 0
121 for(i = 0; i<105; i++)
122 {
123 if(Sem_P(gSemid) != 0)
124 ERR_EXIT("Sem_P");
125
126 value = GetvalueSem(gSemid);
127 printf("信号量值 = %d\n",value);
128
129 Sem_V(gSemid);
130 //value = GetvalueSem(semid);
131 //printf("信号量值 = %d\n",value);
132 }
133 #endif
134
135 return 0;
136 }