XSI-IPC:信号量

1. 信号量简介

命名管道以及消息队列用于一个进程给另一个进程发送数据
与之相比,信号量并不是为了进程间通信,而是提供了一个多个进程间共享的计数器

计数器为正数,进程可以获取信号量(一个或者多个),这时候共享计数器减去进程拿走的数字;也可以放回信号量(一个或者多个),这时候共享计数器加上放回的数字

最重要的是:进程获取信号量时,会得到操作系统支持
[操作系统提示信号量不够减并且进程返回] 或者 [操作系统把调用进程挂起,直到信号量足够减去进程要求的数字时,调用进程返回]

2 信号量结构

  • IPC对象 信号量集
            信号量不能单独表示,它存在于信号量集结构中:一个信号量集可能包含多个信号量
            一个信号量集合对应一个IPC对象,使用一个sem_ds结构表示
    在这里插入图片描述

3 信号量接口

3.1 设计图示

设计三个进程:
进程A负责创建信号量集/IPC 对象 并且该信号量拥有两个信号
信号量初始值设计为10

进程A对信号量1和2进行获取释放操作(一次9个),进程B01,B02分别对信号量01 02进行获取释放操作(一次2个),因为双方进行异步操作,势必发生冲突
在这里插入图片描述

3.2 示例代码(未完成…按照下面的代码,进程A和进程B始终无法产生冲突,待调试)

进程A

#include <iostream> 
extern "C"
{
      #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/sem.h>
	#include <errno.h>
	#include <unistd.h>
	#include <stdio.h>

	/*
		SVr4, POSIX.1-2001.
		int semget(key_t key, int nsems, int semflg);
	
		int semctl(int semid, int semnum, int cmd, ...);

		int semop(int semid, struct sembuf *sops, size_t nsops);
		
	*/
}

using namespace std;

int main()
{
	key_t sem_key = 444;
	unsigned short array[3]={10,10,10};
	int res = 0;

	/**/
	int sem_id = semget(sem_key,3,IPC_CREAT|IPC_EXCL|0600);
	if(-1 ==  sem_id)
	{
		cout << "semget failed,exiting" << endl;
		goto ErrEnd;
	}
	
	/**/
	res = semctl(sem_id,2,SETALL,array);
	if(-1 == res)
	{
		cout << "semctl init failed,exiting" << endl;
		goto ErrEnd;
	}
/*
*/
	struct sembuf oparr[4];
	oparr[0].sem_num = 0;
	oparr[0].sem_op = 9;
	oparr[0].sem_flg = IPC_NOWAIT|SEM_UNDO;

	oparr[1].sem_num = 1;
	oparr[1].sem_op = 9;
	oparr[1].sem_flg = IPC_NOWAIT|SEM_UNDO;

	oparr[2].sem_num = 0;
	oparr[2].sem_op = -9;
	oparr[2].sem_flg = IPC_NOWAIT|SEM_UNDO;


	oparr[3].sem_num = 1;
	oparr[3].sem_op = -9;
	oparr[3].sem_flg = IPC_NOWAIT|SEM_UNDO;

	while(1)
	{
		
		res = semop(sem_id,oparr,1);
		if(res == -1)
		{
			if(errno == EAGAIN)	
			{
				cout << "0 Egain try" << endl;
			}
			else
			{
				cout << "0 Other case" << endl;
			}
		}
		else
		{	
			sleep(3);
			res = semop(sem_id,&oparr[2],1);
			if(res == -1)
			{
				cout << "0 release failed" << endl;
			}
			else
			{
				cout << "0 release ok" << endl;
			}
			sleep(1);
		}
		


		res = semop(sem_id,&oparr[1],1);
		if(res == -1)
		{
			if(errno == EAGAIN)	
			{
				cout << "1 Egain try" << endl;
			}
			else
			{
				cout << "1 Other case" << endl;
			}		
		}
		else
		{	
			res = semop(sem_id,&oparr[3],1);
			if(res == -1)
			{
				cout << "1 release failed" << endl;
			}
			else
			{
				cout << "1 release ok" << endl;
			}
			sleep(1);

		}
		

		
	}
	return 0;

	ErrEnd:
	semctl(sem_id,0,IPC_RMID);
	return -1;
}

进程B

#include <iostream> 
extern "C"
{
      #include <sys/types.h>
      #include <sys/ipc.h>
      #include <sys/sem.h>
      #include <stdio.h>
	#include <errno.h>
	#include <unistd.h>


	/*
		SVr4, POSIX.1-2001.
		int semget(key_t key, int nsems, int semflg);
	*/
}

using namespace std;



int main(int argc, char* argv[])
{
	key_t sem_key = 444;
	int sem_id = semget(sem_key,0,0600);
	if(-1 ==  sem_id)
	{
		cout << "semget open failed,exiting" << endl;
		return -1;
	}
	

	int sem_num = 0;
	if(*argv[1] == '1')
	{
		sem_num = 1;
	}

	struct sembuf oparr[2];
	oparr[0].sem_num = sem_num;
	oparr[0].sem_op = 2;
	oparr[0].sem_flg = IPC_NOWAIT|SEM_UNDO;

	oparr[1].sem_num = sem_num;
	oparr[1].sem_op = -2;
	oparr[1].sem_flg = IPC_NOWAIT|SEM_UNDO;
	
	while(1)
	{
		int res = semop(sem_id,oparr,1);
		if(res == -1)
		{
			if(errno == EAGAIN)	
			{
				cout << "Egain " << sem_num << endl;
			}
			else
			{
				cout << "other case" << endl;
			}
		}
		else
		{	
			sleep(3);
			res = semop(sem_id,&oparr[1],1);
			if(res == -1)
			{
				cout << "release failed" << endl;
			}
			else
			{
				cout << "release ok" << endl;
			}
			sleep(1);
		}
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
06-03

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值