54.1 概述
POSIX共享内存能够让无关程序共享一个映射区域而无需创建一个相应的映射文件。
linux使用挂载与/dev/shm目录下的专用tmpfs文件系统,系统上POSIX共享内存区域占据的内存总量受限于底层的tmpfs文件系统大小(默认256M),超级用户可以使用mount -o remount,size=<num-bytes>重新挂载这个文件系统来修改。
使用共享内存的步骤:
- 使用shm_open()函数打开一个与指定名字对应的对象。
- 将上一步获得的文件描述符传入mmap()调用并在其flags参数中指定MAP_SHARED.这会将共享内存对象映射进进程的虚拟地址空间。
54.2 创建共享内存对象![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ed32eeec91df3f683010bdddada99b91.png)
shm_open函数的参数与open计较类似。
oflag参数的位值:
一个新共享内存对象被创建时其初始长度会被设置为0,这意味着在创建完一个新共享内存对象之后通常在调用mmap()之后可能还需要使用ftruncate()来设置对象的大小。
可以通过fstat(文件描述符)来获取一个stat结构,该结构会包含这个共享内存对象相关的信息。
54.3 使用共享内存对象
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include "string.h"
#include "unistd.h"
int main()
{
int shmfd = shm_open("/demo_shm", O_CREAT|O_RDWR, 0);
if(shmfd == -1){
std::cerr << "shm_open" <<std::endl;
exit(1);
}
ftruncate(shmfd,1024);
char *addr = (char*)mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
if(addr == MAP_FAILED){
std::cerr << "mmap" <<std::endl;
}
memcpy(addr,"hello dylan", 11);
close(shmfd);
}
通过mmap系统调用获取共享内存地址,直接通过memcpy对该地址进行操作。
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include "string.h"
#include "unistd.h"
#include "stdlib.h"
#include "stdio.h"
#include "errno.h"
int main()
{
int shmfd = shm_open("/demo_shm", O_RDONLY, 0);
if(shmfd == -1){
//std::cerr << "shm_open" <<std::endl;
perror("shm_open");
exit(1);
}
ftruncate(shmfd,1024);
char *addr = (char*)mmap(NULL, 1024, PROT_READ, MAP_SHARED, shmfd, 0);
if(addr == MAP_FAILED){
std::cerr << "mmap" <<std::endl;
}
write(STDOUT_FILENO,addr, 11);
close(shmfd);
}
这里直接输出到标准输出。(这里的可能会需要管理员权限!)
54.4 删除共享内存对象
POSIX共享内存具备内和持久性,即它们会持续存在直到被显式删除或系统重启。
可以通过shm_unlink删除它:
一旦所有的进程都解除映射这个对象,对象就会被删除,其中的内容就会丢失。