进程间通信—信号量

IPC标识符和关键字:

在终端输入ipcs,可以看到目前系统中所有的IPC信息:


第一列的key就是IPC的关键字,第二列是IPC的标识符。

ftok()函数用于获得一个IPC的关键字,其函数原型是:

key_t  ftok(const char *pathname,int proj_id);


下面是一个信号量的综合实例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/shm.h>
#if defined(_GNU_LIBRARY_)&&!defined(_SEM_SEMUN_UNDEFINED)
#else
union semun{
	int val;
	struct semid_ds *bur;
	unsigned short *array;
	struct seminfo *_but;
};
#endif
int semheld=0;
int id=0;
void pid_printf(char *format,...)
{
	va_list ap;
	va_start(ap,format);
	printf("[%d]:",getpid());
	vprintf(format,ap);
}

void sem_release(int id)
{
	struct sembuf sb;
	if(semheld < 1)
	{
		pid_printf("I don't have any reources,nothing to release\n");
		return;
	}
	sb.sem_num=0;
	sb.sem_op=1;
	sb.sem_flg=SEM_UNDO;
	if(semop(id,&sb,1) == -1)
	{
		pid_printf("Semop release error:%s\n",strerror(errno));
		exit(-1);
	}
	semheld--;
	pid_printf("Resource released.\n");
}

void sem_request(int id)
{
	struct sembuf sb;
	if(semheld > 0)
	{
		pid_printf("I already hold the resource; not requesting another one.\n");
		return;
	}
	sb.sem_num=0;
	sb.sem_op=-1;
	sb.sem_flg=SEM_UNDO;
	pid_printf("Requesting resource...");
	fflush(stdout);
	if(semop(id,&sb,1) == -1)
	{
		pid_printf("Semop request error:%s\n",strerror(errno));
		exit(-1);
	}
	semheld++;
	printf("Done...\n");
}

void sem_delete(void)
{
	printf("Master exiting ; delete semaphore.\n");
	if(semctl(id,0,IPC_RMID,0) == -1)
	{
		pid_printf("Error releasing semaphore.\n");
	}
}
int main(int argc,char **argv)
{
	union semun sunion;
	if(argc <2)
	{
		id=semget(IPC_PRIVATE,1,SHM_R|SHM_W);
		if(id != -1)
		{
			atexit(sem_delete);
			sunion.val=3;
			if(semctl(id,0,SETVAL,sunion) == -1)
			{
				pid_printf("semctl failed:%s\n",strerror(errno));
				exit(-1);
			}
		}
	}
	else
	{
		id=atoi(argv[1]);
		pid_printf("Using existing semaphore %d.\n",id);
	}
	if(id == -1)
	{
		pid_printf("Semaphore request failed:%s.\n",strerror(errno));
		return 0;
	}
	pid_printf("Sucessfully allocated semaphore id %d.\n",id);
	while(1)
	{
		int action;
		printf("\nStatus:%d request held by this process.\n",semheld);
		printf("please selesct:\n");
		printf("1. Release a resource\n");
		printf("2. Request a resource\n");
		printf("3. Exit this process\n");
		printf("Your choice:");
		scanf("%d",&action);
		switch(action)
		{
			case 1:
				sem_release(id);
				break;
			case 2:
				sem_request(id);
				break;
			case 3:
				exit(0);
				break;
		}
	}
	return 0;
}

测试这个程序,需要分别在两个终端进行操作。现在第一个终端运行程序,并选择2申请资源。

屏幕输出如下:



进程创建了一个ID为65536的信号量集,并申请了一个资源。

我们从另一个终端输入ipcs 命令可以查看到这个信号量集:


在另一个终端在执行这个程序,把信号量ID作为参数传入:


选择2,这事进程会被阻塞,直到另一个进程把资源释放掉,切到另一个终端,输入1,此时可以看到第二个终端的程序马上申请到了资源。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值