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

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;
	}
	else
		return semId;
}

/*******这个子函数用于初始化信号量*******/
int setSem(int semId)
{
	union semun se;
	se.val = 1;//设置信号量的初始值为1
	if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量
	{
		cerr << "init fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******这个子函数删除信号量*******/
int delSem(int semId)
{
	union semun se;
	if (semctl(semId, 0, IPC_RMID, se) < 0)
	{
		cerr << "delete fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******信号量P(等待)V(发布)操作*******/
int P_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = -1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "P error!" << endl;
		return -1;
	}
	else
		return 0;
}

int V_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = 1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "V error!" << endl;
		return -1;
	}
	else
		return 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;
	}
	else
		return semId;
}

/*******这个子函数用于初始化信号量*******/
int setSem(int semId)
{
	union semun se;
	se.val = 1;//设置信号量的初始值为1
	if (semctl(semId, 0, SETVAL, se) == -1)//初始化这个信号量
	{
		cerr << "init fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******这个子函数删除信号量*******/
int delSem(int semId)
{
	union semun se;
	if (semctl(semId, 0, IPC_RMID, se) < 0)
	{
		cerr << "delete fail!" << endl;
		return -1;
	}
	else
		return 0;
}

/*******信号量P(等待)V(发布)操作*******/
int P_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = -1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "P error!" << endl;
		return -1;
	}
	else
		return 0;
}

int V_Sem(int semId)
{
	struct sembuf buf;
	buf.sem_num = 0;//操作单个信号量的时候该参数为0
	buf.sem_op = 1; //-1表示P操作,1表示V操作
	buf.sem_flg = SEM_UNDO;
	if (semop(semId, &buf, 1) < 0)
	{
		cerr << "V error!" << endl;
		return -1;
	}
	else
		return 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值