共享内存
2025/9/4...大约 3 分钟OS
共享内存(Shared Memory)是一种高效的进程间通信(IPC)方式,简单来说,它直接操作的是内存,但它的初始化和持久化选项可以(并非必须)与文件关联
下面用一个表格帮你快速梳理两种主要共享内存方式的核心区别:
特性 | 文件支持的共享内存 (mmap with file) | 匿名共享内存 (mmap with MAP_ANONYMOUS) |
---|---|---|
底层关联 | 磁盘上的一个具体文件 | 无文件关联,纯内存操作 |
映射方式 | 通过 mmap 将文件映射到进程地址空间 | 通过 mmap 设置 MAP_ANONYMOUS 标志创建 |
数据持久化 | 可选择将修改同步至磁盘文件 (MS_SYNC) 或由内核决定稍后写入 (MS_ASYNC) | 进程退出后数据消失,仅用于进程间通信 |
典型应用 | 进程间大量数据共享、需持久化的数据交换 | 父子进程或有亲缘关系进程间的高速、临时数据共享 |
优点 | 数据可持久化;非亲缘进程也能共享 | 无需文件操作,极速;避免磁盘I/O瓶颈 |
缺点 | 仍需文件系统操作(创建/打开文件) | 数据不能持久化;只能用于有亲缘关系的进程 |
🧠 理解其工作方式:
共享内存的核心是 让多个进程的虚拟地址空间映射到相同的物理内存页。这样,一个进程对这块内存的修改,其他进程立刻可见
- 创建与映射:进程使用
mmap()
系统调用发起映射。- 对于文件支持的共享内存,
mmap()
会建立进程虚拟内存与文件某部分内容的关联。注意,此时文件内容并未全部读入内存,而是采用按需加载,即进程访问某个地址时若发现数据不在物理内存中,会触发“缺页中断”,再由内核将相应的文件内容读入物理内存页。 - 对于匿名共享内存,
mmap()
直接分配物理内存页并映射到进程的虚拟地址空间,与文件无关。
- 对于文件支持的共享内存,
- 读写操作:进程通过指针直接读写映射的内存区域,这是在直接操作内存,速度非常快。如果映射方式是
MAP_SHARED
,那么这些修改对其他映射了同一区域的进程是立即可见的,并且对于文件支持的映射,后续也会反映到文件上。 - 同步与解除映射:
- 使用
msync()
可以强制将内存中的修改同步回文件(针对文件支持的映射) - 使用
munmap()
解除映射关系。对于MAP_SHARED
的文件映射,解除时内核通常会将被修改过的内存页写回文件。
- 使用
⚡ 需要注意的问题:
- 同步机制是关键:由于多个进程能同时访问同一内存区域,必须使用同步机制(如信号量、互斥锁)来协调读写操作,防止数据竞争。
- 内存与文件的大小关系:物理内存按页(通常4KB)管理。如果文件大小不是页大小的整数倍,映射区域末尾可能会有“碎片空间”。访问这部分内容可能引发总线错误(Bus error)或段错误(Segmentation fault)。
💎 总结一下:
你可以根据是否需要数据持久化和进程间亲缘关系来选择:
- 若需数据持久化或非亲缘进程共享,用文件支持的共享内存 (
mmap
普通文件,flags
用MAP_SHARED
)。 - 若仅亲缘进程间进行高速临时数据共享,用匿名共享内存 (
mmap
使用MAP_ANONYMOUS
和MAP_SHARED
)。