共享内存在Linux和Windows下使用区别


一、共享内存定义

共享内存是一种用于实现进程间通信(IPC)的方法,不同进程通过访问同一块内存区域实现数据共享和交互,是最快的可用IPC形式(其他进程间通信方式有:信号、管道、消息队列、网络套接字)。

每个进程可以将自身的虚拟地址映射到物理内存中的特定区域,当不同进程将相同的物理内存区域与各自的虚拟地址空间关联时,这些进程就能实现通过共享内存来完成IPC。若某进程更改了共享内存区的内容,其它进程都会觉察到该区域的更改。

每个进程有自己的进程控制块和地址空间,且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。


二、Linux下使用

1.基本思路

Linux下共享内存可以通过tmpfs文件系统来实现,tmpfs默认的挂载目录为/dev/shm,它是基于RAM的文件系统,因此读写速度与读写内存速度一样,在不用的时候系统会自动删除掉。

首先利用shm_open()创建或者打开一个共享内存文件,然后ftruncate()将文件大小设置为共享内存大小,mmap()再将该文件映射到内存。

2.关键函数

#include <sys/mman.h>
int shm_open(const char* name, int oflag, mode_t mode);

参数说明:

名称含义
name打开或创建的共享内存文件名,由于shm_open打开或操作的文件都是位于/dev/shm目录的,因此name不能设置为绝对路径
oflag打开文件操作属性,可通过或运算进行合理组合
O_CREAT:若此文件不存在则进行创建
O_RDWR:打开读写权限
O_EXCL : 如果同时指定了O_CREAT,而文件已经存在,则报错
mode文件权限位,例如0777,可读写执行

注意:返回值表示文件描述字,如成功则大于0,失败则小于0

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

参数说明:

名称含义
addr要将文件映射到的内存地址,设置为nullptr表示由系统决定映射区的起始地址
len映射区的长度
mode文件权限位,例如0777,可读写执行
prot期望的内存保护标志,不能与文件的打开模式冲突,可通过或运算进行合理组合
PROT_EXEC:页内容可以被执
PROT_READ:页内容可以被读取
PROT_WRITE:页可以被写入
PROT_NONE:页不可访问
flags指定映射对象的类型,映射选项和映射页是否可以共享
MAP_SHARED:与其它所有映射这个对象的进程共享映射空间,对共享区的写入,相当于输出到文件
MAP_PRIVATE:建立一个写入时拷贝的私有映射,内存区域的写入不会影响到原文件,这个标志和以上标志是互斥的,只能使用其中一个
MAP_ANONYMOUS:匿名映射,映射区不与任何文件关联
fd有效的文件描述字。一般是由open()函数返回,其值也可以设置为-1,此时需要指定flags参数中的MAP_ANON,表明进行的是匿名映射
offset被映射对象内容的起点

三、Windows下使用

1.基本思路

Windows下共享内存是通过FileMapping实现的。

首先CreateFileMapping()创建内存映射文件对象,即在物理内存申请一块指定大小的内存区域,返回文件映射对象的句柄。然后MapViewOfFile()能够访问内存区域,促使Windows将此内存空间映射到进程的地址空间中。当在其他进程访问这块内存区域时,OpenFileMapping()取得对象句柄,进行读写操作。

2.关键函数

#include <windows.h>
HANDLE WINAPI CreateFileMapping(
_In_HANDLE hFile,
_In_opt_LPSECURITY_ATTRIBUTES lpAttributes,
_In_DWORD flProtect,
_In_DWORD dwMaximumSizeHigh,
_In_DWORD dwMaximumSizeLow,
_In_opt_LPCTSTR lpName);

参数说明:

名称含义
hFile创建映射的一个文件句柄,0xFFFFFFFF(-1,即INVALID_HANDLE_VALUE)表示在页面文件中创建一个可共享的文件映射
lpFileMappigAttributes表明返回的句柄是否可以被子进程所继承,指定一个安全对象,在创建文件映射时使用,如果为nullptr,表示使用默认安全对象
flProtect下述常数之一:
PAGE_READONLY:以只读方式打开映射
PAGE_READWRITE:以可读、可写方式打开映射
PAGE_WRITECOPY :为写操作留下备份
dwMaximumSizeHigh文件映射的最大长度的高32位
dwMaximumSizeLow文件映射的最大长度的低32位,如这个参数和dwMaximumSizeHigh都是零,就用磁盘文件的实际长度
lpName指定文件映射对象的名字,如存在这个名字的一个映射,函数就会打开它

注意:CreateFileMapping()可以用GetLastError()来检查其返回的错误信息。

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

参数说明:

名称含义
hFileMappingObject为CreateFileMapping()或OpenFileMapping()返回的文件映像对象句柄
dwDesiredAccess映射对象的文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配,可取以下值:
FILE_MAP_ALL_ACCESS:文件映射对象被创建时必须指定PAGE_READWRITE 选项.
FILE_MAP_COPY:可以读取和写入文件,写入操作会导致系统为该页面创建一份副本
FILE_MAP_EXECUTE:可以将文件中的数据作为代码来执行
FILE_MAP_READ :可以读取文件
FILE_MAP_WRITE:可以读取和写入文件
dwFileOffsetHigh表示文件映射起始偏移的高32位
dwFileOffsetLow表示文件映射起始偏移的低32位(64KB对齐不是必须的)
dwNumberOfBytes指定映射文件的字节数

四、共享内存优缺点

  • 优点:进程间通信效率高,通过直接访问内存,是最快的IPC可用形式。不同于其他进程间通信方式,只需拷贝两次数据(输入数据->共享内存区->输出数据)。
  • 缺点:没有提供进程同步机制,需借助其他手段(如信号量),解决进程间协作关系。
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值