Linux共享内存、消息队列通信详解

在这里插入图片描述##共享内存通信
在linux内核中创建一段共享内存,使用shmget函数:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
第一个参数key定义是否创建一个带密钥的共享内存。

include <stdio.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
	int shmid;
	int key;
	key=ftok("./a.c",'a');
	if(key<0)
    {
        printf("creat key failure\n");
        return -1;
    }
    printf("creat key sucess key=%X\n",key);

	shmid=shmget(key,128,IPC_CREAT|0777);
	if(shmid<0)
	{
		printf("creat share memory failure\n");
		return -1;
	}
	printf("creat share memory sucess shmid=%d\n",shmid);
	system("ipcs -m");
	system("ipcrm -m shmid");
	return 0;
}

shmat:将共享内存映射到用户空间.
void *shmat(int shmid, const void *shmaddr, int shmflg);
返回值为指针类型,指向用户空间的某个地址,该地址可通过shmaddr变量进行设置。若由内存自行分配,可以设置为NULL

shmdt:将用户空间的映射内存删除
int shmdt(const void *shmaddr);

shmctl:对用内核空间的共享内存进行操作
1、读取对象属性
2、设置对象属性
3、删除对象属性
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

#include <stdio.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	int shmid;
	int key;
	char *p;
	key=ftok("./a.c",'a');
	if(key<0)
    {
        printf("creat key failure\n");
        return -1;
    }
    printf("creat key sucess key=%X\n",key);

	shmid=shmget(key,128,IPC_CREAT|0777);
	if(shmid<0)
	{
		printf("creat share memory failure\n");
		return -1;
	}
	printf("creat share memory sucess shmid=%d\n",shmid);
	system("ipcs -m");
	p=(char *)shmat(shmid,NULL,0);
	if(p==NULL)
	{
		printf("shmet function failure\n");
		return -3;
	}
	fgets(p,128,stdin);
	printf("share memory data:%s",p);
	shmdt(p);
//	memcmp(p,"abcd",4);
	shmctl(shmid,IPC_RMID,NULL);
	system("ipcs -m");
	return 0;
}

对共享内存的总结:
对共享内存的实现步骤:首先要创建内存空间,将内存空间映射到用户空间,使用标准输入输出函数对内存内容进行读取,(共享内存可分为有血缘关系的用户进程和无血缘关系的用户进程,这里可以通过是否选择ftok创建key值)然后是删除共享内存空间。
##消息队列
在linux内核中通过msgget打开或创建队列。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
通过msgsnd和msgrcv函数来队列发送信息或从内核接收信息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
下列代码是实现队列的双向通信
A进程

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
struct msgbuf
{
	long type;
	char voltage[124];
	char ID[4];
};
int main()
{
	int msgid;
	int readret;
	int key;
	int pid;
	struct msgbuf sendbuf,revbuf;
	key=ftok("./a.c",'a');
	if(key<0)
	{
		printf("creat key filure\n");
		return -2;
	}
	msgid=msgget(key,IPC_CREAT|0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
	return -1;
	}
	printf("creat message queue sucess:msgid=%d\n",msgid);
	system("ipcs -q");
	pid=fork();
	if(pid==0)//
	{
		sendbuf.type=200;
		while(1)
		{
			memset(sendbuf.voltage,0,124);
			printf("please input message:\n");
			fgets(sendbuf.voltage,124,stdin);
			msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
		}
	}
	if(pid>0)
	{	
		while(1)
		{
			memset(revbuf.voltage,0,124);
			msgrcv(msgid,(void *)&revbuf,124,100,0);
			printf("revbuf.voltage=%s\n",revbuf.voltage);
		}
	}
	
	//删除消息队列
	msgctl(msgid,IPC_RMID,NULL);
	system("ipcs -q");
	return 0;
}

B进程

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
struct msgbuf
{
	long type;
	char voltage[128];
	char ID[4];
};
int main()
{
	int msgid;
	int readret;
	int key;
	int pid;
	struct msgbuf sendbuf,revbuf;
	key=ftok("./a.c",'a');
	if(key<0)
	{
		printf("creat key filure\n");
		return -2;
	}
	msgid=msgget(key,IPC_CREAT|0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
	return -1;
	}
	printf("creat message queue sucess:msgid=%d\n",msgid);
	system("ipcs -q");
	pid=fork();
	if(pid>0)//
	{
		sendbuf.type=100;
		while(1)
		{
			memset(sendbuf.voltage,0,128);
			printf("please input message:\n");
			fgets(sendbuf.voltage,128,stdin);
			msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
		}
	}
	if(pid==0)
	{	
		while(1)
		{
			memset(revbuf.voltage,0,128);
			msgrcv(msgid,(void *)&revbuf,128,200,0);
			printf("revbuf.voltage=%s\n",revbuf.voltage);
		}
	}
	
/*	system("ipcs -q");
	memset(revbuf.voltage,0,128);
	readret=msgrcv(msgid,(void *)&revbuf,128,100,0);
	printf("revbuf.voltage=%s\n",revbuf.voltage);
*/
	//删除消息队列
	msgctl(msgid,IPC_RMID,NULL);
	system("ipcs -q");
	return 0;
}

结构体中long字段必须具有严格的正整数值。 接收过程可以使用此值进行消息选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值