进程通信 二、XSI进程间通信之共享内存

共享内存是内核中开辟一块内存由IPC对象进行管理,进程A、B都用纸自己的虚拟地址与之映射,这样就达到了共享同一块内存。

特点:
	优点:不需要复制信息,是最快的一种进程间通信机制。
	缺点:需要考虑同步问题(必须借助其他机制,如信号)

***编程模型***
               进程A					进程B
生成IPC键值	ftok					生成IPC键值	ftok
创建共享内存	shmget					获取共享内存	shmget
映射共享内存	shmat					映射共享内存	shmat
使用共享内存	*ptr					使用共享内存	*ptr
取消映射		shmdt					取消映射		shmdt
删除共享内存	shmctl				         ...

共享内存所使用的函数:

#include <sys/ipc.h>
#include <sys/shm.h>	
Int  shmget(key_t  key, size_t  size, int  shmflg);
功能:创建或获取共享内存
key:IPC键值,由ftok函数生成
size:共享内存的大小,最好是4096的整数倍,(获取共享内存时,此值无效)
shmflg:
	0			获取共享内存
	IPC_CREAT 	创建
	IPC_EXCL  	如果存在则创建失败
返回值:成功返回共享内存标识(IPC标识),失败返回-1

void  *shmat(int  shmid, const void  *shmaddr, int  shmflg);
功能:映射共享内存
shmid	:共享内存标识符,shmget的返回值
shmaddr:进程提供的虚拟地址,与内核中的内存映射,也可以是NULL(内核自动选择一个地址映射)
shmflg:	
	0            	自动分配
	SHM_RDONLY 	只读权限
	SHM_RND    	当shmaddr不为NULL时,shmaddr向下去整页
返回值:映射成功后的虚拟地址

Int  shmdt(const void  *shmaddr);
功能:取消虚拟地址与共享内存的映射
shmaddr:被映射过的虚拟地址

int  shmctl(int  shmid, int  cmd, struct shmid_ds  *buf);
功能:删除共享内存,获取/设置共享内存的属性
shmid:共享内存标识符shmget的返回值
cmd:
	IPC_STAT		获取共享内存的属性
	IPC_SET		设置共享内存的属性
	IPC_RMID		删除共享内存 buf = NULL

buf:(获取/设置)
	struct shmid_ds 
	{
		struct ipc_perm shm_perm;   	 内存的所有者及权限 	/* Ownership and permissions */
		size_t          shm_segsz;  	 内存的大小				/* Size of segment (bytes) */
		time_t          shm_atime; 	  最后的映射时间			/* Last attach time */
		time_t          shm_dtime;   	最后的取消映射时间		/* Last detach time */
		time_t          shm_ctime; 	  最后修改时间			/* Last change time */
		pid_t             shm_cpid;   	 创建者进程ID			/* PID of creator */
		pid_t             shm_lpid;    	最后映射/取消映射的进程ID/* PID of last shmat(2)/shmdt(2) */
		shmatt_t        shm_nattch;  	映射的次数				/* No. of current attaches */
		...
    };
	 
	struct ipc_perm 
	{
		key_t          __key;   	 IPC键值				/* Key supplied to shmget(2) */
		uid_t          uid;      	有效用户ID	 		/* Effective UID of owner */
		gid_t          gid;     	 有效组ID			/* Effective GID of owner */
		uid_t          cuid;   	 创建者的用户ID			/* Effective UID of creator */
		gid_t          cgid;     	创建者的组ID			/* Effective GID of creator */
		unsigned short mode;   	  权限					/* Permissions + SHM_DEST and SHM_LOCKED flags */
		unsigned short __seq;  	  IPC标识				/* Sequence number */
	};

共享内存进程A实现代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/shm.h>
#include<signal.h>

int main()
{
	//1.创建IPC键值
	key_t key = ftok(".",8888);

	//2. 创建共享内存
	int shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0644);
	if(0 > shmid)
	{
		perror("shmget");
		return -1;
	}

	//3.映射
	char* str = shmat(shmid,NULL,SHM_RND);
	if(NULL == str)
	{
		perror("shmat");
		return -1;
	}

	//4.使用
	pid_t pid = 0;
	printf("请输入要通信的进程号:");
	scanf("%u",&pid);
	stdin->_IO_read_ptr = stdin->_IO_read_end;
	while(1)
	{
		printf(">");
		gets(str);
		kill(pid,SIGINT);
		if(0 == strcmp(str,"quit"))
		{
			printf("通信结束\n");
			break;	
		}
	}
	//5.取消映射
	if(0 > shmdt(str))
	{
		perror("shmdt");
		return -1;
	}
	//6.删除共享内存
	if(0 > shmctl(shmid,IPC_RMID,NULL))
	{
		perror("shmctl");
		return -1;
	}
	return 0;	
}

共享内存进程B实现代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/shm.h>
#include<signal.h>

int main()
{	
	printf("进程id:%u\n",getpid());
	//1. 创建IPC键值
	key_t key = ftok(".",8888);
	
	//2.获取共享内存
	int shmid = shmget(key,0,0);
	if(0 > shmid)
	{
		perror("shmget");
		return -1;
	}

	//3.映射
	char* str = shmat(shmid,NULL,SHM_RND);
	if(NULL == str)
	{
		perror("shamt");
		return -1;
	}

	//4.使用
	void sigint(int sig)
	{
		printf("read:%s\n",str);
		if(0 == strcmp(str,"quit"))
		{
			printf("通信结束\n");
			if(0 > shmdt(str))
			{
				perror("shmdt");
			}
			exit(0);	
		}
	}
	signal(SIGINT,sigint);
	while(1);
	pause();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值