1 #include <stdio.h>
2 #include <sys/sem.h>
3 #include <sys/ipc.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <pthread.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10
11 typedef int semophore;
12 //semophore mutex = 1;
13 semophore cnt = 0;
14 //semophore db = 1;
15 char mutex[] = "mutex";
16 char db[] = "db";
17 int semId;
18 void read(int cnt)
19 {
20 fprintf(stdout, "NO.%d reading...\n",cnt);
21 //for (int i = 0; i < 1000000; i++);
22 sleep(1);
23 fprintf(stdout, "NO.%d read finished.\n",cnt);
24
25 }
26 void write()
27 {
28 fprintf(stdout, "writing...\n");
29 //for (int i = 0; i < 1000000; i++);
30 sleep(1);
31 fprintf(stdout, "write finished.\n");
32 }
33
34 union semun {
35 int val;
36 struct semid_ds *buf;
37 unsigned short int *array;
38 struct seminfo *__buf;
39 };
40
41 void p(const char *s)
42 {
43 semun arg;
44 int tmp;
45 int r;
46 if (strcmp(s, mutex) == 0)
47 {
48 //fprintf(stdout,"mutex:%d\n",semctl(semId, 0, GETVAL, arg));
49 while(1){
50 if(semctl(semId, 0, GETVAL, arg)<=0)
51 wait(&r);
52 else break;
53 }
54 tmp = semctl(semId, 0, GETVAL, arg);
55 //if(tmp<=0) waitpid();
56 arg.val = tmp - 1;
57 semctl(semId, 0, SETVAL, arg);
58 }
59 else if (strcmp(s, db) == 0)
60 {
61 //fprintf(stdout,"db:%d\n",semctl(semId, 1, GETVAL, arg));
62 while(1){
63 if(semctl(semId, 1, GETVAL, arg)<=0)
64 wait(&r);
65 else break;
66 }
67 tmp = semctl(semId, 1, GETVAL, arg);
68 arg.val = tmp - 1;
69 semctl(semId, 1, SETVAL, arg);
70 }
71 }
72 void v(const char *s)
73 {
74 semun arg;
75 int tmp;
76 if (strcmp(s, mutex) == 0)
77 {
78 tmp = semctl(semId, 0, GETVAL, arg);
79 arg.val = tmp + 1;
80 semctl(semId, 0, SETVAL, arg);
81 }
82 else if (strcmp(s, db) == 0)
83 {
84 tmp = semctl(semId, 1, GETVAL, arg);
85 arg.val = tmp + 1;
86 semctl(semId, 1, SETVAL, arg);
87 }
88 }
89
90 void* reader(void* args)
91 {
92 p(mutex);
93 cnt++;
94 if (cnt == 1)
95 {
96 p(db);
97 }
98 v(mutex);
99
100 read(cnt);
101
102 p(mutex);
103 cnt--;
104 if (cnt == 0)
105 {
106 v(db);
107 }
108 v(mutex);
109 }
110 void* writer(void* args)
111 {
112 p(db);
113 write();
114 v(db);
115 }
116
117 int main()
118 {
119 semun arg;
120 if ((semId = semget(1, 2, IPC_CREAT | IPC_EXCL | 0666)) >= 0)
121 {
122 arg.val = 1;
123 if (semctl(semId, 0, SETALL, arg) < 0)
124 {
125 fprintf(stdout, "semctl error %s\n", strerror(errno));
126 return -1;
127 }
128
129 }
130 else if (errno == EEXIST)
131 {
132 semId = semget(1, 2, 0666);
133 }
134 else
135 {
136 fprintf(stdout, "semget error %s\n", strerror(errno));
137 return -1;
138 }
139 pthread_t tids[5];
140 for(int i = 0; i < 5; ++i)
141 {
142 //fprintf(stdout,"turn NO.%d\n",i);
143 //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
144 if(i==0 || i==2 || i==4)
145 {
146 int ret = pthread_create(&tids[i], NULL, reader, NULL);
147 if (ret != 0)
148 {
149 fprintf(stdout, "reading error\n");
150 }
151 }
152 else{
153 int ret = pthread_create(&tids[i], NULL, writer, NULL);
154 if (ret != 0)
155 {
156 fprintf(stdout, "writing error\n");
157 }
158 }
159 }
160
161 pthread_exit(NULL);
162 return 0;
163 }