各平台共享内存的实现方式

UNIX

在内存共享问题上,UNIX历史上主要有两个标准:Posix与System V,相比来说Posix标准更符合统一风格要求,与文件系统结合,更易于使用。除了这两个标准,还有一种基于磁盘文件映射的机制。

Posix

Posix标准提供一种共享内存文件设备,通过访问共享内存文件设备来实现进程间的数据共享。共享内存文件是通过shm_open创建,通过shm_unlink删除,这和普通文件的创建很相似。shm_open包含创建与打开两个动作,如果已经存在的话,也是通过shm_open打开。可以指定一些flag规定shm_open的行为,比如不存在时是否创建,是否排出已存在的实例,以及打开的读写权限。

       #include <sys/mman.h>
       #include <sys/stat.h>        /* For mode constants */
       #include <fcntl.h>           /* For O_* constants */

       int shm_open(const char *name, int oflag, mode_t mode);

       int shm_unlink(const char *name);

刚创建的共享内存文件长度为0,一般需要马上扩展其长度,和普通文件一样,通过 ftruncate调整长度。

       #include <unistd.h>
       #include <sys/types.h>

       int ftruncate(int fd, off_t length);

在共享内存不使用的时候,通过close关闭,和普通文件关闭的接口是同一个。关闭不会删除共享内存文件,即使最后一个打开被close了也不会删除,之后还可以再打开。只有调用shm_unlink才会删除共享内存文件。

       #include <unistd.h>

       int close(int fd);

如果要访问共享数据,需要将共享内存文件映射到进程空间,mmap被用来实现这个映射,而munmap解除相应的映射。mmap还有其他的应用方式,与系统内存相关的操作几乎都离不开mmap和munmap。

       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

System V

System V共享内存是System V IPC的成员,没有与文件绑定,但是通过ipc命令如ipcs,ipcrm可以操作System V IPC对象。输入ipcs命令会打印下面的内容:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      

------ Semaphore Arrays --------
key        semid      owner      perms      nsems     

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    

其中Shared Memory Segments就是共享内存。

可以看到ipc对象的前四项属性是所有ipc类型都有的,key是访问的索引值,打开时由使用者指定;id是ipc内部分配的编号,在打开时返回;owner是所有者id;perms是权限信息。

在命令行中,可以通过ipcrm命令删除ipc对象。ipcrm的参数指定删除那种对象,-m表示共享内存(Shared Memory Segments),-s表示信号量集(Semaphore Arrays),-q表示消息队列(Message Queues),也可以是大写的-M、-S、-Q,小写使用内部id查找,大写使用key查找。在ipc对象被删除后,内部id会变成0,就不能再被打开了。

打开和创建System V共享内存的接口是shmget,key可以随便指定,保证唯一且不等于-1就行。

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

int shmget(key_t key, size_t size, int shmflg);

也可以通过库函数 ftok 来生成一个唯一的key。

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);

ftok使用一个文件名和一个唯一id作为参数,这个id虽然是int类型,但是只有8位被使用,所以只能传一个字节,另外标准中规定不能为0。

 

#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);


 

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

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

 

File Map

       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);


 

Windows

FileMapping

HANDLE WINAPI CreateFileMapping(
  __in      HANDLE hFile,
  __in_opt  LPSECURITY_ATTRIBUTES lpAttributes,
  __in      DWORD flProtect,
  __in      DWORD dwMaximumSizeHigh,
  __in      DWORD dwMaximumSizeLow,
  __in_opt  LPCTSTR lpName
);

 

 

HANDLE WINAPI OpenFileMapping(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  LPCTSTR lpName
);


 

BOOL WINAPI CloseHandle(
  __in  HANDLE hObject
);


 

LPVOID WINAPI MapViewOfFile(
  __in  HANDLE hFileMappingObject,
  __in  DWORD dwDesiredAccess,
  __in  DWORD dwFileOffsetHigh,
  __in  DWORD dwFileOffsetLow,
  __in  SIZE_T dwNumberOfBytesToMap
);


 

BOOL WINAPI UnmapViewOfFile(
  __in  LPCVOID lpBaseAddress
);


 

File Map

HANDLE WINAPI CreateFile(
  __in      LPCTSTR lpFileName,
  __in      DWORD dwDesiredAccess,
  __in      DWORD dwShareMode,
  __in_opt  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  __in      DWORD dwCreationDisposition,
  __in      DWORD dwFlagsAndAttributes,
  __in_opt  HANDLE hTemplateFile
);


 

BOOL WINAPI CloseHandle(
  __in  HANDLE hObject
);


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fighting Horse

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

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

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

打赏作者

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

抵扣说明:

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

余额充值