2、程序员造轮子:共享内存编程(包装类)

初级代码游戏的专栏介绍与文章目录-CSDN博客

github位置:codetoys/ctfc.git src/function/myshm.h   

       关于共享内存的介绍看这里:

UNIX/LINUX编程:共享内存-CSDN博客

        这里继续对编程接口进行介绍。下面提供了一个共享内存包装类。基本上能用到的都在这里了(因为我用了好多年)。

        其实挺简单的。

目录

一、总代码

二、详解

2.1 创建

2.2 连接

2.3 断开

2.4 删除

2.5 获取状态

 三、结束语


一、总代码

        代码是64位的,可以运行在IBM\HP\SUN的小型机和x86-64的Linux服务器上。

#include <errno.h>
#include <sys/shm.h>
#include <sys/ipc.h>

typedef char * PSHM;

	class CShmMan
	{
	public:
		static PSHM ConnectByID(int id,bool isreadonly,void * addr=NULL)
		{
			PSHM pshm;
			if((pshm=(PSHM)shmat(id,addr,(isreadonly?SHM_RDONLY:0)))==(PSHM)(-1L))
			{
				return NULL;
			}
			return pshm;
		}
		static PSHM ConnectByKey(key_t key,bool isreadonly)
		{
			int shmid;
			if(0>(shmid=shmget(key,0,SHM_R|(SHM_R>>3)|(SHM_R>>6)|SHM_W|(SHM_W>>3)|(SHM_W>>6))))
			{//必须是已经存在的
				return NULL;
			}
			PSHM pshm;
			if((pshm=(PSHM)shmat(shmid,0,(isreadonly?SHM_RDONLY:0)))==(PSHM)(-1L))
			{
				return NULL;
			}
			return pshm;
		}
		static int CreatePrivateSHM(long size){return CreateSHMByKey(IPC_PRIVATE,size);}
		static int CreateSHMByKey(key_t key,long size)
		{
			int shmid;
			if(0>(shmid=shmget(key,size,SHM_R|(SHM_R>>3)|(SHM_R>>6)|SHM_W|(SHM_W>>3)|(SHM_W>>6)|IPC_CREAT|IPC_EXCL)))
			{//必须不是已经存在的
				//LOG<<"shmid "<<shmid<<ENDE;
				return -1;
			}
			return shmid;
		}

		//删除共享内存,删除后不可再使用
		static bool Destory(int shmid)
		{
			if(shmctl(shmid,IPC_RMID,0)<0)
			{
				return false;
			}
			return true;
		}
		static bool Disconnect(PSHM p)
		{
			if(0!=shmdt(p))
			{
				return false;
			}
			return true;
		}

		static bool GetState(int shmid,size_t & size,time_t & ctime)
		{
			shmid_ds ds;

			if(0!=shmctl(shmid,IPC_STAT,&ds))
			{
				return false;
			}

			size=ds.shm_segsz;
			ctime=ds.shm_ctime;

			return true;
		}
	};

二、详解

2.1 创建

        有两个不同的函数:CreatePrivateSHM和CreateSHMByKey:

		static int CreatePrivateSHM(long size){return CreateSHMByKey(IPC_PRIVATE,size);}
		static int CreateSHMByKey(key_t key,long size)

        这两个函数内部调用IPC函数shmget创建共享内存,区别仅仅是指定KEY还是不使用KEY。

        按照C函数的传统习惯,shmget既可以创建也可以连接,传统处理此类功能的逻辑是通过参数区分“如果不存在就创建”或者“如果不存在就失败”。现在我们主张把创建和访问分开,比较符合正常逻辑(也就是为什么要把这几个简单函数包装一下)。

2.2 连接

        连接可分两种,通过KEY连接和通过ID连接,通过KEY连接其实是先通过KEY获取ID,然后再通过ID连接:

		static PSHM ConnectByID(int id,bool isreadonly,void * addr=NULL)
		{
			PSHM pshm;
			if((pshm=(PSHM)shmat(id,addr,(isreadonly?SHM_RDONLY:0)))==(PSHM)(-1L))
			{
				return NULL;
			}
			return pshm;
		}
		static PSHM ConnectByKey(key_t key,bool isreadonly)
		{
			int shmid;
			if(0>(shmid=shmget(key,0,SHM_R|(SHM_R>>3)|(SHM_R>>6)|SHM_W|(SHM_W>>3)|(SHM_W>>6))))
			{//必须是已经存在的
				return NULL;
			}
			PSHM pshm;
			if((pshm=(PSHM)shmat(shmid,0,(isreadonly?SHM_RDONLY:0)))==(PSHM)(-1L))
			{
				return NULL;
			}
			return pshm;
		}

        这里面参数有点讲究:

  • isreadonly 可以做只读连接,这样会杜绝用户误修改数据的可能,毕竟,跑飞的指针可不管你是什么内存
  • void * addr 指定连接地址,前文介绍过,这种方式很困难,但是如果确实可以用,可以省不少事

2.3 断开

        断开很简单,断开之后共享内存的连接数减一。

2.4 删除

        删除也很简单,不过,删除是延迟的,删除操作只会把共享内存设置为删除状态,阻止新的连接,当连接数为0时才真正删除。也就是说,如果有个程序一直挂着,这块内存共享不会被释放,系统可用的内存不会增加,新的创建操作很可能会因为物理内存不足而失败。

2.5 获取状态

        为了确保连接的是正确的共享内存,应该检查共享内存的状态。状态信息包括创建时间、大小和连接数,连接数当然没什么用,创建时间和大小可以用来确认是不是预期的共享内存。

		static bool GetState(int shmid,size_t & size,time_t & ctime)
		{
			shmid_ds ds;

			if(0!=shmctl(shmid,IPC_STAT,&ds))
			{
				return false;
			}

			size=ds.shm_segsz;
			ctime=ds.shm_ctime;

			return true;
		}

 三、结束语

        到这里你就能建立自己的共享内存程序了,剩下的功夫就在数据结构上了。

(这里是结束)

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值