系统相关
首页 > 系统相关> > linux网络编程-进程间通信——信号量2

linux网络编程-进程间通信——信号量2

作者:互联网

  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 initValue, int semNum)
 18 {
 19     union semun sem;
 20     sem_t semid;
 21     sem.val = initValue;
 22 
 23     semid = semget(key, 5, IPC_CREAT | IPC_EXCL | 0666);//创建信号量个数为1
 24     if(-1 == semid)
 25     {
 26         ERR_EXIT("semget");
 27     }
 28     for(int i=0;i<semNum;i++)
 29     {
 30         semctl(semid, i, SETVAL, sem);//参数2-要操作的信号量在信号量集中的编号;参数3-cmd...
 31     }
 32     return semid;
 33 }
 34 
 35 int Sem_P(sem_t semid)
 36 {
 37     //sops有三种方式,0-默认阻塞、IPC_NOWAIT-非阻塞、SEM_UNDO-撤销上一次操作
 38     struct sembuf sops={0,-1,0};
 39     return (semop(semid,&sops,1));
 40 }
 41 
 42 int Sem_V(sem_t semid)
 43 {
 44     struct sembuf sops={0,+1,0};
 45     return (semop(semid,&sops,1));
 46 }
 47 
 48 void SetvalueSem(sem_t semid, int value)
 49 {
 50     union semun sem;
 51     sem.val = value;
 52     
 53     semctl(semid,0,SETVAL,sem);
 54 }
 55 
 56 int GetvalueSem(sem_t semid)
 57 {
 58     union semun sem;
 59     return semctl(semid,0,GETVAL,sem);
 60 }
 61 
 62 void DestroySem(sem_t semid)
 63 {
 64     union semun sem;
 65     sem.val = 0;
 66     semctl(semid,0,IPC_RMID,sem);
 67 }
 68 
 69 void Print(char opChar)
 70 {
 71     int pauseTime;
 72     srand(getpid());
 73     int i;
 74 
 75     for(i=0; i<10; i++)
 76     {
 77         if(Sem_P(gSemid) != 0)
 78             ERR_EXIT("Sem_P");
 79         //临界区-begin
 80         printf("%c", opChar);
 81         fflush(stdout);
 82         pauseTime = rand()%3;
 83         sleep(pauseTime);
 84         printf("%c", opChar);
 85         fflush(stdout);
 86         //临界区-end
 87         Sem_V(gSemid);
 88         pauseTime = rand()%2;
 89         sleep(pauseTime);
 90     }
 91 }
 92 #define DELAY (rand()%5+1)
 93 
 94 void waitFor2Fork(int phiNum)
 95 {
 96     int ret = 0;
 97     int left = phiNum;//哲学家左侧 筷子编号
 98     int right = (phiNum+1)%5;
 99     struct sembuf buf[2] = {
100         {left, -1, 0},
101         {right, -1, 0}
102     };
103     //同时拿起左侧右侧的筷子,则不会发生死锁
104     //如果没有被释放,则等待
105     ret = semop(gSemid, buf, 2);
106     if(-1 == ret)
107     {
108         ERR_EXIT("waitFor2Fork");
109     }
110 }
111 void free2Fork(int phiNum)
112 {
113     int left = phiNum;//哲学家左侧 筷子编号
114     int right = (phiNum+1)%5;
115     struct sembuf buf[2] = {
116         {left, +1, 0},
117         {right, +1, 0}
118     };
119     //同时放下筷子
120     semop(gSemid, buf, 2);
121 }
122 
123 void waitForLeftFork(int phiNum)
124 {
125     int ret = 0;
126     int left = phiNum;//哲学家左侧 筷子编号
127     int right = (phiNum+1)%5;
128     struct sembuf buf = {left, -1, 0};
129     //同时拿起左侧右侧的筷子,则不会发生死锁
130     //如果没有被释放,则等待
131     ret = semop(gSemid, &buf, 1);
132     if(-1 == ret)
133     {
134         ERR_EXIT("waitForLeftFork");
135     }
136 }
137 void waitForRightFork(int phiNum)
138 {
139     int ret = 0;
140     int left = phiNum;//哲学家左侧 筷子编号
141     int right = (phiNum+1)%5;
142     struct sembuf buf = {right, -1, 0};
143     //同时拿起左侧右侧的筷子,则不会发生死锁
144     //如果没有被释放,则等待
145     ret = semop(gSemid, &buf, 1);
146     if(-1 == ret)
147     {
148         ERR_EXIT("waitForRightFork");
149     }
150 }
151 void freeLeftFork(int phiNum)
152 {
153     int left = phiNum;//哲学家左侧 筷子编号
154     int right = (phiNum+1)%5;
155     struct sembuf buf = {left, +1, 0};
156     //同时放下筷子
157     semop(gSemid, &buf, 1);
158 }
159 void freeRightFork(int phiNum)
160 {
161     int left = phiNum;//哲学家左侧 筷子编号
162     int right = (phiNum+1)%5;
163     struct sembuf buf = {right, +1, 0};
164     //同时放下筷子
165     semop(gSemid, &buf, 1);
166 }
167 //#define LOCK
168 void Philosopher(int phiNum)
169 {
170 #ifdef LOCK
171     for(;;)//有锁
172     {
173         printf("%d is thinking\n",phiNum);
174         sleep(DELAY);
175         printf("%d is hungry\n",phiNum);
176         waitFor2Fork(phiNum);
177         printf("%d is eating\n",phiNum);
178         sleep(DELAY);
179         free2Fork(phiNum);
180     }
181 #else
182     for(;;)//无锁
183     {
184         printf("%d is thinking\n",phiNum);
185         sleep(DELAY);
186         printf("%d is hungry\n",phiNum);
187         waitForLeftFork(phiNum);
188         sleep(5);
189         waitForRightFork(phiNum);
190         printf("%d is eating\n",phiNum);
191         sleep(DELAY);
192         freeLeftFork(phiNum);
193         freeRightFork(phiNum);
194     }
195 #endif
196 }
197 
198 int main(void)
199 {
200     char i;
201     key_t key;
202     int value = 0;
203     int pid;
204     int phiNum = 0;
205         
206     key = ftok("./ipc", 'c');
207     gSemid = CreateSem(key,1, 5);//5个信号量都初始化为1,表示可用的状态
208 
209     for(int i=1; i<5; i++)
210     {
211         pid = fork();
212         if(-1 == pid)
213             ERR_EXIT("fork");
214         if(0 == pid)//子进程
215         {
216             phiNum = i;
217             break;
218         }
219     }
220 
221     Philosopher(phiNum);
222     
223     return 0;
224 }

 

标签:信号量,semid,int,间通信,EXIT,key,linux,sem,include
来源: https://www.cnblogs.com/zzx2bky/p/15914466.html