LinuxC/C++编程(5)—SystemV信号量

来源:互联网 发布:火影忍者知乎 编辑:程序博客网 时间:2024/06/05 20:18

Linux中有多种类型的信号量,其中SystemV是比较重要的一种,常用于多进程同步和进程间通信。常用的函数均包含于<sys/sem.h>中。

参考了一篇很不错的博客文章:点击打开链接

自己写了一个程序,两个进程分别向控制台打印字符串,两个进程几乎一样,只是B进程中没有初始化/删除信号量。

贴代码:

这是A进程,信号量在这个进程中被初始化和删除

//============================================================================// Name        : A.cpp// Author      : Lin// Version     :// Copyright   : Your copyright notice// Description : A demo for processes synchronization using SystemV//============================================================================#include <iostream>#include <unistd.h>#include <string>#include <sys/sem.h>#include <time.h>#include <stdlib.h>using namespace std;union semun{int val;struct semid_ds *buf;unsigned short *arry;};/*******这个子函数用于创建信号量*******/int createSem(){int semId = semget((key_t)1234, 1, 0666|IPC_CREAT);//包含于<sys/sem.h>,创建一个信号量,共用一个key_t key即表示共用一个信号量if (semId < 0){cerr << "create SystemV error! "<< endl;return -1;}elsereturn semId;}/*******这个子函数用于初始化信号量*******/int setSem(int semId){union semun se;se.val = 1;//设置信号量的初始值为1if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量{cerr << "init fail!" << endl;return -1;}elsereturn 0;}/*******这个子函数删除信号量*******/int delSem(int semId){union semun se;if (semctl(semId, 0, IPC_RMID, se) < 0){cerr << "delete fail!" << endl;return -1;}elsereturn 0;}/*******信号量P(等待)V(发布)操作*******/int P_Sem(int semId){struct sembuf buf;buf.sem_num = 0;//操作单个信号量的时候该参数为0buf.sem_op = -1; //-1表示P操作,1表示V操作buf.sem_flg = SEM_UNDO;if (semop(semId, &buf, 1) < 0){cerr << "P error!" << endl;return -1;}elsereturn 0;}int V_Sem(int semId){struct sembuf buf;buf.sem_num = 0;//操作单个信号量的时候该参数为0buf.sem_op = 1; //-1表示P操作,1表示V操作buf.sem_flg = SEM_UNDO;if (semop(semId, &buf, 1) < 0){cerr << "V error!" << endl;return -1;}elsereturn 0;}/*******主函数*******/int main() {string str = "a";int semId = createSem();if (semId == -1)return -1;if (setSem(semId) == -1) //一个信号量只能被初始化/删除一次return -1;double d = 0;srand(time(NULL)); //设置随机数的种子for (int i = 0; i != 10; ++i){P_Sem(semId); //进入临界区d = rand()*1.0/RAND_MAX;  //产生一个0-1之间的随机数,让线程休眠这段时间cout << str << i << " " << d << endl;sleep(d);V_Sem(semId); //离开临界区}P_Sem(semId);if (delSem(semId) == -1) //一个信号量只能被初始化/删除一次return -1;return 0;}

这是B进程,在这个进程中没有信号量的初始化函数,所以这个函数需要先在后台运行,然后再运行A进程(否则这个B进程会因为信号量未被初始化而一直被阻塞)

//============================================================================// Name        : B.cpp// Author      : Lin// Version     :// Copyright   : Your copyright notice// Description : A demo for processes synchronization using SystemV//============================================================================#include <iostream>#include <unistd.h>#include <string>#include <sys/sem.h>#include <stdlib.h>#include <time.h>using namespace std;union semun{int val;struct semid_ds *buf;unsigned short *arry;};/*******这个子函数用于创建信号量*******/int createSem(){int semId = semget((key_t)1234, 1, 0666|IPC_CREAT);//包含于<sys/sem.h>,创建一个信号量,共用一个key_t key即表示共用一个信号量if (semId < 0){cerr << "create SystemV error! "<< endl;return -1;}elsereturn semId;}/*******这个子函数用于初始化信号量*******/int setSem(int semId){union semun se;se.val = 1;//设置信号量的初始值为1if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量{cerr << "init fail!" << endl;return -1;}elsereturn 0;}/*******这个子函数删除信号量*******/int delSem(int semId){union semun se;if (semctl(semId, 0, IPC_RMID, se) < 0){cerr << "delete fail!" << endl;return -1;}elsereturn 0;}/*******信号量P(等待)V(发布)操作*******/int P_Sem(int semId){struct sembuf buf;buf.sem_num = 0;//操作单个信号量的时候该参数为0buf.sem_op = -1; //-1表示P操作,1表示V操作buf.sem_flg = SEM_UNDO;if (semop(semId, &buf, 1) < 0){cerr << "P error!" << endl;return -1;}elsereturn 0;}int V_Sem(int semId){struct sembuf buf;buf.sem_num = 0;//操作单个信号量的时候该参数为0buf.sem_op = 1; //-1表示P操作,1表示V操作buf.sem_flg = SEM_UNDO;if (semop(semId, &buf, 1) < 0){cerr << "V error!" << endl;return -1;}elsereturn 0;}/*******主函数*******/int main() {string str = "b";int semId = createSem();if (semId == -1)return -1;double d = 0;srand(time(NULL)); //设置随机数的种子for (int i = 0; i != 10; ++i){P_Sem(semId); //进入临界区d = rand()*2.0/RAND_MAX;cout << str << i << " " << d << endl;sleep(d);V_Sem(semId); //离开临界区}return 0;}

运行过程如下:先后台运行B进程,再运行A进程


lin@lin-Z97-HD3:~/workspace$ ./B &
[1] 9733
lin@lin-Z97-HD3:~/workspace$ ./A
b0 1.87174
a0 0.274022
b1 0.902205
a1 0.555554
b2 1.49148
a2 0.541172
b3 1.86328
a3 1.59087
b4 1.99479
a4 1.65941
b5 0.353798
a5 0.54769
b6 0.637533
a6 1.29195
b7 0.618795
a7 1.9387
b8 0.38083
a8 1.70235
b9 0.727489
a9 0.851653
[1]+  已完成               ./B

可以看到两个进程轮流向控制台打印字符串

0 0
原创粉丝点击