Linux下使用信号量来进行进程间通信

原创 2013年12月04日 00:26:02

贴一篇代码,我们操作系统老师布置的作业,由单信号量,改为一个信号集中多信号量。水平有限,写的不好。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include<sys/mman.h>   //提供了共享内存的相关操作 
#include<fcntl.h>
#include<sys/stat.h>

union semun {
 	int val;
 	struct semid_ds *buf;
 	unsigned short *array;
} arg;

//生成信号量
//信号量创建
//第一个:同步信号量,表示先后顺序,必须有空间才能生产
//第二个:同步信号量,表示先后顺序,必须有产品才能消费
//第三个:互斥信号量,生产者和每个消费者不能同时进入缓冲区
int sem_creat(key_t key)
{
  	union semun sem[3];
  	int semid;
  	sem[0].val = 5;//最多5个产品
  	sem[1].val=0;
  	sem[2].val=1;
  	semid = semget(key, 3, IPC_CREAT|0666);//三个信号量,空、满、进入缓冲区。
  	if (-1 == semid)
  	{
    		printf("create semaphore error\n");
    		exit(-1);
  	}
  	semctl(semid, 0, SETVAL, sem[0]);//初始信号量集中的第一个信号量
  	semctl(semid,1,SETVAL,sem[1]);//第二个
  	semctl(semid,2,SETVAL,sem[2]);//第三个
  	return semid;
}

//删除信号量
void del_sem(int semid)
{
 	union semun sem;
 	sem.val = 0;
 	semctl(semid, 0, IPC_RMID, sem);
 	semctl(semid, 1, IPC_RMID, sem);
 	semctl(semid, 2, IPC_RMID, sem);
}

//p操作
int p(int semid,int semIndex)
{
 	struct sembuf sops={semIndex, -1, SEM_UNDO};//这里的“semIndex”是信号量集里的信号量序号
 	return (semop(semid, &sops, 1));
}
//v操作
int v(int semid,int semIndex)
{
 	struct sembuf sops={semIndex, +1, SEM_UNDO};//这里的“semIndex”是信号量集里的信号量序号
 	return (semop(semid, &sops, 1));
}

int buffer;
int Num=5;
int *pData;
int value_read = 0, value_write = 0;
int full, empty,all;
int start=0,end=0;

void producer(key_t);
void consumer(int);

int main(void)
{	
	key_t keyFull, keyEmpty,key;
	int fd;
	pid_t pid;
  	void *ptr;   //指向共享内存的指针  

  	/* shm_open是一个POSIX函数,用来打开或创建一个与“/shm”关联的共享内存区 */
	if((fd = shm_open("/shm", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)//shmget(...)
	{
		printf("shm_open error\n"); /* 出错提示 */
	}
	if(ftruncate(fd, sizeof(int)*5) == -1) /* 截短共享内存的长度到我们所需要的长度 */
	{
		printf("ftruncate error\n");
	}
	if((ptr = mmap(0, sizeof(int)*5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) /* 将共享内存映射到进程地址空间 */
	{
		printf("mmap error");
	}   
  
	pData = (int *)ptr;
	//keyFull = ftok("/", 0);
  	//keyEmpty = ftok("/", 1);
  	key=ftok("/", 0);
  	//full = sem_creat(keyFull, 0);
  	//empty = sem_creat(keyEmpty, 1);
  	all=sem_creat(key);
	switch(pid = fork())
	{
		case -1: /* 生成子进程失败 */		
			break;
		case 0: /* 子进程 */
			//producer(keyFull, keyEmpty); /* 子进程是生产者 */		
			producer(key);
      			sleep(2);	
			break;
		default:
			//consumer(full, empty); /* 父进程是消费者 */
			consumer(all);
			break;
  	}
  
  	wait(0);
  	shm_unlink("/shm"); /* 删除共享内存区,程序中基本上保证了子进程先退出,因此父进程中无wait操作且这部操作放在父进程这里 */
	//shmctl(shmid,IPC_RMID,&buf);
 	//del_sem(semid);
	return 0;
}

/* 生产者写5次后退出 */
//void producer(key_t keyFull, key_t keyEmpty)
void producer(key_t key)
{
  	//full = semget(keyFull, 3, 0);
  	//empty = semget(keyEmpty, 3, 0);
  	all=semget(key,3,0);

	while(value_write < 10) /* 退出条件判定 */
	{
    		//printf("Prepare Write\n");
		printf("准备写\n");
    		//printf("empty Write P1 : %d\n", semctl(empty, 0, GETVAL, 0));
		p(all,0); //判断是否有空	
		p(all,2);//操作缓冲区
    		//printf("empty Write P2 : %d\n", semctl(empty, 0, GETVAL, 0));	
		value_write++; 
		*(pData+start%Num) = value_write;
		//printf("Write : %5d\n", *(pData+start%Num));
		printf("写 : %5d\n", *(pData+start%Num));		 
		start++; 
    		//printf("full Write V1 : %d\n", semctl(full, 0, GETVAL, 0));  	
		v(all,2);//释放缓冲区
		v(all,1); //通知消费者
    		//printf("full Write V2 : %d\n", semctl(full, 0, GETVAL, 0));
    		//printf("Write Finish\n");
		printf("写结束\n");
    		//sleep(3);
	}
}

/* 消费者读5次后退出 */
//void consumer(int full, int empty)
void consumer(int all)
{
  	while(value_read < 10) /* 退出条件判定 */
	{ 
    		//printf("		Prepare Read\n");
		printf("		准备读\n");
    		//printf("		full Read P1 : %d\n", semctl(full, 0, GETVAL, 0));
		p(all,1);//判断是否有产品
		p(all,2); //操作缓冲区
    		//printf("		full Read P1 : %d\n", semctl(full, 0, GETVAL, 0));	
		//printf("		Read : %5d\n", *(pData+end%Num));	
		printf("		读 : %5d\n", *(pData+end%Num));
    		//printf("		empty Read V1 : %d\n", semctl(empty, 0, GETVAL, 0));	
    		//printf("		empty Read V1 : %d\n", semctl(empty, 0, GETVAL, 0));
    		//value_read ++;
    		//printf("		Read Finish\n");
		printf("		读结束\n");
		if(*(pData+end%Num) == 10)
			exit(0);
		end++;
		v(all,2);//释放缓冲区
		v(all,0);//通知生产者
		//sleep(1);
	}
}
//gcc -lrt p.c (-o 目标文件名)
//./a.out


版权声明:本文为博主原创文章,未经博主允许不得转载。

【Linux进程间通信】 - 信号量

前面我们在介绍共享内存(传送门: 【Linux进程间通信】 - 共享内存)这种进程间通信时方式时提到,使用共享内存通信时需要使用同步机制来控制多个进程对统一内存区的读写操作。今天我们就来讲述一种常用的...
  • Xiejingfa
  • Xiejingfa
  • 2016年03月16日 17:01
  • 1436

【Linux】进程间通信-信号量详解及编程实例

前面一篇文章线程同步之信号量同步 讲的是线程之间的信号量,这篇讲的更加具有通用性,能够实现进程之间的同步。 信号量概述 信号量定义: 它是一个特殊变量,只允许对它进行等待和发送信号这...
  • xiajun07061225
  • xiajun07061225
  • 2013年01月07日 10:58
  • 16285

进程间通信方式之信号量

信号量,又称信号灯,主要用于进程间以及同一进程不同线程间的同步手段,用来解决进程间的同步与互斥问题的一种进程之间通信机制,包括一个称为信号量的变量和在该变信号量下等待资源的进程等待队列,以及对信号量进...
  • Echo_Ana
  • Echo_Ana
  • 2016年10月28日 16:02
  • 697

进程间通信系列 之 信号量详解及编程实例

进程间通信(IPC,Interprocess communication)是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息。这使得一个程序能够在同一时间...
  • iamonlyme
  • iamonlyme
  • 2013年11月13日 08:41
  • 1758

Linux进程间通信——使用信号量

这篇文章将讲述别一种进程间通信的机制——信号量。注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物。下面就进入信号量的讲解。 一、什么是信号量 为了防止出现因多个程序同时访问一个...
  • ljianhui
  • ljianhui
  • 2013年08月24日 00:12
  • 118118

【Linux】进程间通信(IPC)之信号量详解与测试用例

学习环境centos6.5 Linux内核2.6进程间通信概述进程通信机制一般情况下,系统中运行着大量的进程,而每个进程之间并不是相互独立的,有些进程之间经常需要互相传递消息。但是每个进程在系统中都有...
  • a1414345
  • a1414345
  • 2017年03月22日 17:28
  • 810

共享内存多进程间通信,进程间同步使用信号量来实现

Linux 环境下C编程指南,通过共享内存进行进程间通信的例子,进程间同步使用信号量来实现。 代码 11-5 使用说明:这是一个简单的服务器和客户端程序,如果启动程序时不带参数,则执行服务器程序;...
  • haoren001
  • haoren001
  • 2013年11月09日 15:40
  • 3836

Linux进程间通信 共享内存+信号量+简单例子

每一个进程都有着自己独立的地址空间,比如程序之前申请了一块内存,当调用fork函数之后,父进程和子进程所使用的是不同的内存。因此进程间的通信,不像线程间通信那么简单。但是共享内存编程接口可以让一个进程...
  • u012377333
  • u012377333
  • 2015年08月25日 17:43
  • 1837

linux的进程通信:信号量实例(C语言)

linux的进程通信:信号量实例(C语言) 2012-01-06 06:25:49 标签:信号量 进程 通信 linux C 原创作品,允许转载,转载时请务必以超链接形式标明文章 原...
  • chrysanthemumcao
  • chrysanthemumcao
  • 2013年07月02日 18:50
  • 1211

进程间通信之信号量

何为信号量 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、...
  • qq_33724710
  • qq_33724710
  • 2016年09月02日 13:58
  • 1017
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux下使用信号量来进行进程间通信
举报原因:
原因补充:

(最多只允许输入30个字)