7.4 POSIX 共享内存
前面提到的内存映射允许无关进程共享内存区域以执行相应的 IPC,但具有一些缺点,比如它需要在硬盘上创建相应的文件,存在额外的 IO 开销。为了克服这些缺点,提出了 共享内存 API。 使用 POSXI 共享内存一般需要以下步骤:
使用
shm_open
函数打开一个共享内存对象,此函数返回一个引用该对象的文件描述符。将上一步获得的文件描述符传入
mmap
调用并指定 flags 参数中指定 MAP_SHARED,即可将共享内存对象映射到虚拟地址空间。此文件描述符上可以调用传统 Unix 文件描述符系统调用。
创建共享内存对象
shm_open
函数创建和打开一个新的共享内存对象或打开一个既有对象,它的参数与 open 函数类似:
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
/*
@brief 打开一个文件
@param name 标识出了待创建或待打开的共享内存对象
@param flags 掩码表,可取:
- O_CREAT 对象不存在时创建,若同时指定 O_EXCL,则对象存在时返回错误
- O_RDONLY 只读访问
- O_RDWR 读写访问
- O_TRUNC 将对象截断为 0
@param mode 标识文件的所有权限,在创建共享内存对象时使用
仅仅打开一个已有对象需要将其设置为 0
- S_IRUSR | S_IWUSR 属主的读写权限
- S_IRGRP | S_IWGRP 数组的读写权限
- S_IROTH | S_IWOTH 其它的去写权限
@return 成功返回文件描述符,失败返回 -1
*/
int shm_open(const char *name, int oflag, mode_t mode);
shm_open
返回的文件描述符会设置 close-on-exec 标记,因此当程序执行了一个 exec 时文件描述符会被自动关闭。 共享内存对象在创建后其初始长度会被设置为 0,所以在调用 mmap
之前调用 ftruncate
来设置对象的大小。并且在内存映射后继续调用 ftruncate
来操作映射内存大小。
删除共享内存对象
SUSv3 要求 POSIX 共享内存对象至少具备内核持久性,即它们会持续存在直到被显式删除或系统重启。当不再需要一个共享内存对象时就应该使用shm_unlink
删除它:
#include <sys/mman.h>
int shm_unlink(const char *name);
shm_unlink
函数会删除通过 name 指定的共享内存对象。删除一个共享内存对象不会影响对象的既有映射(它会保持有效直到相应的进程调用 munmap
或终止),但会阻止后续的 shm_open
调用打开这个对象。一旦所有进程都解除映射这个对象,对象就会被删除,其中的内容会丢失。
最后更新于
这有帮助吗?