进程间的通信---共享内存、消息队列

进程间的通信:共享内存 消息队列

1.共享内存

定义:
共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
原理:
为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。
共享内存
共享内存程序编写步骤:
A程序:1 ftok(“.”,int a)–>flag找到A进程的标识–>B进程通过该flag找到A进程
2 shmget
3 shmat
4 memcpy
B程序 1 ftok
2 shmget
3 shmat //做映射
4 printf() //直接用数据

key_t ftok(const char *pathname,int proj_id);
作用:生成对方进程找到自己的标识符
参数1:*pathname:用户指定的路径,可以是“.”,或“/home/farsight/…”
参数2: proj_id:范围:0~255
返回值: 成功:产生一个key值
失败:-1

int shmget(key_t key,int size,int shmflg);
作用:创建一块共享内存
参数1:key:IPC_PRIVATE或ftok的返回值
参数2:size:共享内存的大小
参数3:shmflg:操作共享内存的权限
返回值:成功:返回一个有效的shmID—>表示创建成功的共享内存。
失败:-1

void *shmat(int shmid,const void *shmaddr,int shmflg);
作用:将本地内存和共享内存建立映射
参数1:shmid:共享内存的标识符,shmget的返回值
参数2:*shmaddr:指向内本地内存地址的指针,一般给NULL;
参数3:shmflg:SHM_RDONLY–>共享内存只读
0–>共享内存可读写
返回值:指向映射成功后的本地内存地址;

void *memcpy(void *dest, const void *src, size_t n);

shmat函数
int shmdt(const void *shmaddr);
*shmaddr:映射成功后的本地内存地址,shmat的返回值。

int shmctl(int shmid,int cmd,struct shmid_ds *buf);
作用:设置或获取共享内存属性
参数1:shmid:共享内存的表示符,shmget的返回值
参数2:cmd:操作选项IPC_STAT(获取对象属性)
IPC_SET(设置对象属性)
IPC_RMID(删除对象)
参数3:*buf:指向共享内存的属性值,IPC_STAT或IPC_SET时使用,IPC_RMID时该值置为NULL;

由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。

共享内存编写的程序:
程序A

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define SHM_SIZE 256
int main()
{
	key_t key=0;
	//1.ftok
	key=ftok(".",10);
	if(-1==key)
	{
		printf("生成标识符出错\r\n");
		return -1;
	}
	printf("1:ftok ok,key=%d\r\n",key);
	//2.shmget
	int id=0;
	id=shmget(key,SHM_SIZE,IPC_CREAT|0666);
	if(-1==id)
	{
		printf("创建共享内存失败\r\n");
		return -1;
	}
	printf("2:shmget ok,shmid=%d\r\n",id);
	//3.shmat
	char *add=(char *)shmat(id,NULL,0);
	char str[]="hello";
	//4.memcpy
	memset(add,0,SHM_SIZE);
	memcpy(add,str,sizeof(str));
	printf("%s\r\n",add);
	//取消映射
	shmdt(add);
	//删除共享内存
	//shmctl(id,IPC_RMID,NULL);
	return 0;
}

程序B

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define SHM_SIZE 256
int main()
{
	key_t key=0;
	//1.ftok
	key=ftok(".",10);
	if(-1==key)
	{
		printf("生成标识符出错\r\n");
		return -1;
	}
	printf("1:ftok ok,key=%d\r\n",key);
	//2.shmget
	int id=0;
	id=shmget(key,SHM_SIZE,0666);
	if(-1==id)
	{
		printf("找共享内存失败\r\n");
		return -1;
	}
	printf("2:shmget ok,shmid=%d\r\n",id);
	//3.shmat
	void *add=shmat(id,NULL,0);
	if((void *)-1==add)
	{
		printf("shmat error----\r\n");
		return -1;
	}
	printf("shmat OK\r\n");
	//4.printf
	char *p=(char *)add;
	printf("read data:%s\r\n",p);
	//取消映射
	shmdt(add);
	printf("unshmat ok!\r\n");
	//删除共享内存
	//shmctl(id,IPC_RMID,NULL);
	return 0;
}

2.消息队列

消息:要传递信息的目标载体
队列:先进先出
A发:1.ftok
2.msgget 创建消息队列
3.创建消息节点
4.msgsnd
B收:1.ftok
2.msgget
3.msgrcv

函数:int msgget(key_t key, int msgflg);
作用:创建一个消息队列 key:ftok的返回值
msgflg:消息队列的访问权限,创建得或上IPC_CREAT|返回权限
返回值:成功:标识消息队列的id,失败:-1;
消息节点:一般由消息类型和消息正文组成
struct msgbuf
{
long m_type;//消息类型 char
buf[BUF_SIZE];//消息正文,BUF_SIZE为消息大小
}

函数:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
作用:给消息队列发消息
参数1:msgid:消息队列ID
参数2:msgp:指向消息结构体的指针
参数3:msgsz:消息的大小
参数4:msgflg:IPC_NOWAIT 消息没有发送完成函数也会立即返回
0:指导发送完成函数返回
返回值:0成功,-1失败

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
作用:从消息队列中读消息
参数1:msgid:消息队列ID
参数2:msgp:指向消息结构体的指针
参数3:msgsz:消息的大小
参数4:msgtyp:
msgtyp
参数5:msgflg:IPC_NOWAIT 消息没有发送完成函数也会立即返回
0:指导发送完成函数返回
返回值:成功:期望接收到的消息长度大小(而非实际接收到的长度)
失败:-1

案例:A程序:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define BUF_SIZE 50
struct msgbuf
{
	long m_type;
	char m_buf[BUF_SIZE];
}
int main()
{
	//1 ftok
	key_t key=ftok(".",18);
	if(-1==key)
	{
		printf("ftok error!------\r\n");
		return -1;
	}
	printf("1:ftok ok!-----------\r\n");
	//2 msgget
	int msgID=msgget(key,IPC_CREAT|0666);
	if(-1==msgID)
	{
		printf("msgget error\r\n");
		return -1;
	}
	printf("2:msgget ok!--------\r\n");
	//3 struct msgbuf
	struct msgbuf stBuf;
	memset(&stBuf,0,sizeof(struct msgbuf));
	stBuf.m_type=2;
	strcpy(stBuf.m_buf,"hello world");

	//4 msgsnd
	if(0==msgsnd(msgID,(void *)&stBuf,BUF_SIZE,0))
	{
		printf("send message ok!\r\n");
	}
	return 0;
}

案例B程序

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define BUF_SIZE 50
struct msgbuf
{
	long m_type;
	char m_buf[BUF_SIZE];
};
int main()
{
	//1 ftok
	key_t key=ftok(".",18);
	if(-1==key)
	{
		printf("ftok error!------\r\n");
		return -1;
	}
	printf("1:ftok ok!-----------\r\n");
	//2 msgget
	int msgID=msgget(key,0666);
	if(-1==msgID)
	{
		printf("msgget error\r\n");
		return -1;
	}
	printf("2:msgget ok!--------\r\n");
	//3 struct msgbuf
	struct msgbuf stBuf;
	memset(&stBuf,0,sizeof(struct msgbuf));

	//4 msgrcv
	int ret=msgrcv(msgID,(void *)&stBuf,BUF_SIZE,0,0);
	if(ret>0)
	{
		printf("recvice message ok!ret=%d buf:%s\r\n",ret,stBuf.m_buf);
	}
	else
	{
		printf("message recv error!\r\n");
	}
	return 0;
}

运行结果:
案例结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值