linux进程间通讯-共享内存

  1.原理
         多个进程申请同一块内存区域,然后使用这个内存区域来通信
     查看共享内存
         ipcs  -m
     删除共享内存
         ipcrm  -m  共享内存的ID号

   2.相关的接口函数
         (1)申请共享内存
               #include <sys/shm.h>
               int shmget(key_t key, size_t size, int shmflg);
                       返回值:成功  返回共享内存的ID号
                               失败  -1
                         参数:key --》键值,用来帮助你申请共享内存(键值相同,申请的内存区域就是一样)
                                       键值的来源:
                                           第一种:程序员可以自己随便写个无符号的整数
                                           第二种:调用linux提供的ftok()函数产生键值
                                                    #include <sys/types.h>
                                                    #include <sys/ipc.h>
                                                    key_t ftok(const char *pathname, int proj_id);
                                                           原理:该函数源码中有一套算法,根据你传递的路径名和整数计算得到一个唯一的键值
                                                           返回值:成功 返回计算得到的键值
                                                             参数:pathname --》合法的路径名
                                                                   proj_id --》随便写个整数
                                                            ftok("/", 453);
                               size --》你要申请的内存大小,一般写成512字节的整数倍
                               shmflg --》IPC_CREAT  //新建
                                          IPC_EXCL   //如果之前已经申请过同样的共享内存,再次申请就失败
                                                     //O_CREAT和O_EXCL类似
               注意:
                      写法一:shmget(54552,1024,IPC_CREAT|IPC_EXCL|0777);
                              适用于共享内存没有申请过,第一次申请
                      写法二:shmget(54552,1024,0777);
                              适用于共享内存申请过,现在只是把共享内存打开
           (2)映射得到共享内存的首地址
               void *shmat(int shmid, const void *shmaddr, int shmflg);
                       返回值:成功 返回共享内存的首地址
                               失败 NULL
                         参数:shmid --》共享内存的ID号
                               shmaddr --》设置为NULL,让操作系统来给我分配首地址 
                               shmflg --》默认设置为0
           
           (3)解除映射
               int shmdt(const void *shmaddr);
                         参数:shmaddr --》共享内存的首地址

           (4)多功能函数,删除/设置/获取共享内存的属性信息
               int shmctl(int shmid, int cmd, struct shmid_ds *buf);
                         参数:shmid --》共享内存的ID号
                               cmd --》IPC_STAT  获取共享内存的属性信息
                                       IPC_SET   设置共享内存的属性信息
                                       IPC_RMID  删除共享内存
                               buf --》保存共享内存的属性信息
                               struct shmid_ds
                               {
                                   struct  ipc_perm  shm_perm; //权限
                                   shm_segsz; //大小
                               }
                               struct  ipc_perm
                               {
                                   __key;  //键值
                                   mode;    //权限
                               }
                         共享内存的属性:大小,ID号,键值等等这些

 获取共享内存的属性信息

#include "myhead.h"

int main()
{
	int shmid;
	//申请共享内存
	shmid=shmget(54552,1024,IPC_CREAT|IPC_EXCL|0777);
	if(shmid==-1) //发生错误
	{
		//依据刚才讲解的错误码原理,进一步分析产生错误的原因
		if(errno==EEXIST)  //说明错误的原因是共享内存已经存在
		{
			shmid=shmget(54552,1024,0777); //打开共享内存
		}
		else //说明错误是其他类型的错误
		{
			perror("申请共享内存失败了!\n");
			return -1;
		}
		
	}
	struct shmid_ds myds;
	//获取刚才你申请的共享内存的属性信息
	shmctl(shmid,IPC_STAT,&myds);
	//打印你获得的属性信息
	printf("共享内存的大小是:%ld\n",myds.shm_segsz);
	printf("共享内存的键值是:%ld\n",myds.shm_perm.__key);
	printf("共享内存的权限是:%o\n",myds.shm_perm.mode);
	//映射得到共享内存的首地址
	char *p=shmat(shmid,NULL,0);
	//p指向的就是你刚才申请得到的1024字节的内存首地址
	if(p==NULL)
	{
		perror("映射共享内存失败!\n");
		return -1;
	}
	
	//解除映射
	shmdt(p);
	
	
	
	return 0;
}

设置共享内存的属性信息

#include "myhead.h"

int main()
{
	int shmid;
	//申请共享内存
	shmid=shmget(54552,1024,IPC_CREAT|IPC_EXCL|0777);
	if(shmid==-1) //发生错误
	{
		//依据刚才讲解的错误码原理,进一步分析产生错误的原因
		if(errno==EEXIST)  //说明错误的原因是共享内存已经存在
		{
			shmid=shmget(54552,1024,0777); //打开共享内存
		}
		else //说明错误是其他类型的错误
		{
			perror("申请共享内存失败了!\n");
			return -1;
		}
		
	}
	struct shmid_ds myds;
	bzero(&myds,sizeof(myds));
	//初始化
	myds.shm_perm.mode=0666;
	
	//设置共享内存的属性信息
	shmctl(shmid,IPC_SET,&myds);

	//映射得到共享内存的首地址
	char *p=shmat(shmid,NULL,0);
	//p指向的就是你刚才申请得到的1024字节的内存首地址
	if(p==NULL)
	{
		perror("映射共享内存失败!\n");
		return -1;
	}
	
	//解除映射
	shmdt(p);
	
	
	
	return 0;
}

删除共享内存

#include "myhead.h"

int main()
{
	int shmid;
	//申请共享内存
	shmid=shmget(54552,1024,IPC_CREAT|IPC_EXCL|0777);
	if(shmid==-1) //发生错误
	{
		//依据刚才讲解的错误码原理,进一步分析产生错误的原因
		if(errno==EEXIST)  //说明错误的原因是共享内存已经存在
		{
			shmid=shmget(54552,1024,0777); //打开共享内存
		}
		else //说明错误是其他类型的错误
		{
			perror("申请共享内存失败了!\n");
			return -1;
		}
		
	}
	
	//映射得到共享内存的首地址
	char *p=shmat(shmid,NULL,0);
	//p指向的就是你刚才申请得到的1024字节的内存首地址
	if(p==NULL)
	{
		perror("映射共享内存失败!\n");
		return -1;
	}
	
	//解除映射
	shmdt(p);
	
	//删除共享内存
	shmctl(shmid,IPC_RMID,NULL);
	
	return 0;
}

进程之间利用共享内存单向通讯

#include "myhead.h"

int main()
{
	int shmid;
	//申请共享内存
	shmid=shmget(ftok("/home/gec",10),1024,IPC_CREAT|IPC_EXCL|0777);
	if(shmid==-1) //发生错误
	{
		//依据刚才讲解的错误码原理,进一步分析产生错误的原因
		if(errno==EEXIST)  //说明错误的原因是共享内存已经存在
		{
			shmid=shmget(ftok("/home/gec",10),1024,0777); //打开共享内存
		}
		else //说明错误是其他类型的错误
		{
			perror("申请共享内存失败了!\n");
			return -1;
		}
		
	}
	
	//映射得到共享内存的首地址
	char *p=shmat(shmid,NULL,0);
	//p指向的就是你刚才申请得到的1024字节的内存首地址
	if(p==NULL)
	{
		perror("映射共享内存失败!\n");
		return -1;
	}
	
	//p1通过共享内存发送信息给p2
	while(1)
	{
		printf("请输入要发送给p2的信息!\n");
		scanf("%s",p); 
	}
}
#include "myhead.h"
// p2的代码
int main()
{
	int shmid;
	//申请共享内存
	shmid=shmget(ftok("/home/gec",10),1024,IPC_CREAT|IPC_EXCL|0777);
	if(shmid==-1) //发生错误
	{
		//依据刚才讲解的错误码原理,进一步分析产生错误的原因
		if(errno==EEXIST)  //说明错误的原因是共享内存已经存在
		{
			shmid=shmget(ftok("/home/gec",10),1024,0777); //打开共享内存
		}
		else //说明错误是其他类型的错误
		{
			perror("申请共享内存失败了!\n");
			return -1;
		}
		
	}
	
	//映射得到共享内存的首地址
	char *p=shmat(shmid,NULL,0);
	//p指向的就是你刚才申请得到的1024字节的内存首地址
	if(p==NULL)
	{
		perror("映射共享内存失败!\n");
		return -1;
	}
	
	//从共享内存去访问p1存放的信息
	while(1)
	{
		if(strlen(p)!=0)
		{
			printf("p1发送的信息是:%s\n",p);
			bzero(p,1024);
		}
			
	}
	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值