news 2026/4/3 6:26:09

Linux进程间通信mmap与共享内存对比

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux进程间通信mmap与共享内存对比

mmap 与 System V 共享内存对比

概述

mmap 和 System V 共享内存都是 Linux 中用于进程间通信(IPC)的机制, 两者都允许多个进程共享同一块物理内存, 实现零拷贝的高效通信. 本文档从使用方式、特点、实现机制等多个维度进行详细对比.

使用方式对比

API 对比

mmap 相关 API
#include<sys/mman.h>// 创建内存映射void*mmap(void*addr,size_tlength,intprot,intflags,intfd,off_toffset);// 取消映射intmunmap(void*addr,size_tlength);// 同步到文件intmsync(void*addr,size_tlength,intflags);

特点:

  • 统一的 API, 既可用于文件映射, 也可用于匿名映射
  • 需要文件描述符(匿名映射时使用 -1)
  • 直接返回虚拟地址指针
System V 共享内存 API
#include<sys/shm.h>// 创建/获取共享内存段intshmget(key_tkey,size_tsize,intshmflg);// 附加到进程地址空间void*shmat(intshmid,constvoid*shmaddr,intshmflg);// 分离共享内存intshmdt(constvoid*shmaddr);// 控制操作(删除、获取信息等)intshmctl(intshmid,intcmd,structshmid_ds*buf);

特点:

  • 专门的 IPC API, 需要多个步骤
  • 使用键值(key)标识共享内存段
  • 需要显式的 attach/detach 操作

使用流程对比

mmap 使用流程

文件映射方式:

// 1. 打开文件intfd=open("shared.dat",O_RDWR|O_CREAT,0666);ftruncate(fd,size);// 2. 创建映射void*addr=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);// 3. 使用映射区域memcpy(addr,data,size);// 4. 同步(可选)msync(addr,size,MS_SYNC);// 5. 取消映射munmap(addr,size);close(fd);

匿名映射方式:

// 1. 创建匿名映射void*addr=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);// 2. 使用(父子进程通过 fork 共享)// 3. 取消映射munmap(addr,size);
System V 共享内存使用流程
// 1. 生成键值key_tkey=ftok(".",'s');// 2. 创建/获取共享内存段intshmid=shmget(key,size,IPC_CREAT|0666);// 3. 附加到进程地址空间void*addr=shmat(shmid,NULL,0);// 4. 使用共享内存memcpy(addr,data,size);// 5. 分离共享内存shmdt(addr);// 6. 删除共享内存段(可选, 通常由一个进程负责)shmctl(shmid,IPC_RMID,NULL);

标识方式对比

特性mmapSystem V 共享内存
标识方式文件路径 + 文件描述符键值(key) + shmid
键值生成不需要(使用文件路径)需要ftok()IPC_PRIVATE
跨进程共享通过文件路径通过键值
持久性文件映射持久, 匿名映射不持久显式删除前持久

特点对比

功能特性对比

特性mmapSystem V 共享内存
文件关联可以映射文件, 也可以匿名映射不关联文件, 纯内存
持久性文件映射持久, 匿名映射不持久显式删除前持久
同步到文件支持msync()同步到文件不支持文件同步
按需加载支持, 利用虚拟内存按需加载不支持, 一次性分配
大文件处理适合处理大文件不适合, 需要一次性分配全部内存
灵活性高, 可以映射文件、设备、匿名区域中, 只能创建纯内存段
地址选择可以指定地址或让系统选择可以指定地址或让系统选择

性能特点对比

性能指标mmapSystem V 共享内存
零拷贝✅ 是✅ 是
直接内存访问✅ 是✅ 是
延迟低(直接内存访问)极低(直接内存访问)
吞吐量高(零拷贝)极高(零拷贝)
CPU占用
内存占用按需加载, 节省内存一次性分配, 占用固定内存
缺页处理支持, 按需加载文件内容不支持, 内存已分配

同步机制需求

两者都需要用户空间的同步机制:

同步机制mmapSystem V 共享内存
内核保护❌ 无❌ 无
需要同步✅ 是✅ 是
常用同步方式信号量、互斥锁、原子操作信号量、互斥锁、原子操作
同步复杂度相同相同

实现机制对比

内核实现对比

mmap 实现机制

核心数据结构:

  • vm_area_struct(VMA): 虚拟内存区域描述符
  • mm_struct: 进程地址空间描述符
  • file: 文件对象(文件映射时)

实现路径:

sys_mmap2 → do_mmap_pgoff → - 地址选择(get_unmapped_area) - VMA 创建和初始化 - 文件映射(file->f_op->mmap) 或匿名映射(shmem_zero_setup) - VMA 插入到进程地址空间

关键特点:

  • 基于虚拟内存管理(VMA)
  • 文件映射使用页缓存(page cache)
  • 匿名映射使用 shmem 文件系统
  • 支持按需加载(缺页处理)
System V 共享内存实现机制

核心数据结构:

  • shmid_kernel: 共享内存段描述符
  • shmem_inode_info: shmem 文件系统 inode
  • kern_ipc_perm: IPC 权限和键值管理

实现路径:

sys_shmget → newseg → - 创建 shmid_kernel - 创建 shmem 文件(shmem_file_setup) - 安装到 IPC ID 表 sys_shmat → do_shmat → - 权限检查 - 调用 do_mmap_pgoff 映射 shm_file - 更新附加计数

关键特点:

  • 基于 IPC 框架(键值、权限管理)
  • 内部使用 shmem 文件系统
  • 最终通过 mmap 机制映射到进程地址空间
  • 需要显式的 attach/detach 操作

内存管理对比

方面mmapSystem V 共享内存
内存分配时机按需分配(缺页时)创建时一次性分配
物理页管理页缓存或匿名页shmem 文件系统页
换入换出支持(除非 MAP_LOCKED)支持(除非 SHM_LOCK)
内存锁定MAP_LOCKED 标志SHM_LOCK 命令
页表管理通过 VMA 管理通过 VMA 管理(内部使用 mmap)

文件系统依赖

特性mmapSystem V 共享内存
文件系统文件映射依赖文件系统, 匿名映射使用 shmem内部使用 shmem, 用户不可见
文件可见性文件映射时文件可见文件不可见(内部使用)
文件同步支持 msync 同步到文件不支持文件同步

适用场景对比

mmap 适用场景

适合:

  • 大文件处理(按需加载)
  • 需要文件持久化的场景
  • 数据库、缓存等需要文件映射的应用
  • 需要高效文件 I/O 的场景
  • 父子进程通过 fork 共享内存

不适合:

  • 简单的进程间通信(管道更合适)
  • 不需要文件关联的纯内存共享

System V 共享内存适用场景

适合:

  • 大数据量传输
  • 对性能要求极高的场景
  • 需要频繁通信的场景
  • 不需要文件关联的纯内存共享
  • 需要显式生命周期管理的场景

不适合:

  • 需要文件持久化的场景
  • 大文件处理(需要一次性分配全部内存)
  • 需要按需加载的场景

优缺点对比

mmap 优缺点

优点:

  1. ✅ 功能强大: 既可以映射文件, 也可以匿名映射
  2. ✅ 按需加载: 利用虚拟内存机制, 节省内存
  3. ✅ 文件同步: 支持同步到文件, 数据持久化
  4. ✅ 大文件处理: 适合处理大文件, 无需一次性加载
  5. ✅ 灵活性高: 可以映射文件、设备、匿名区域
  6. ✅ 标准 POSIX API: 跨平台兼容性好

缺点:

  1. ❌ API 相对复杂: 需要理解虚拟内存概念
  2. ❌ 文件依赖: 文件映射依赖文件系统
  3. ❌ 匿名映射共享: 父子进程共享需要 fork, 独立进程共享需要文件
  4. ❌ 同步机制: 需要用户空间同步机制

System V 共享内存优缺点

优点:

  1. ✅ 性能极高: 零拷贝, 直接内存访问
  2. ✅ 简单直接: 专门的 IPC API, 语义清晰
  3. ✅ 持久性: 显式删除前一直存在
  4. ✅ 独立进程通信: 不要求进程间有亲缘关系
  5. ✅ 生命周期管理: 显式的创建、附加、分离、删除

缺点:

  1. ❌ 内存占用: 一次性分配全部内存, 不能按需加载
  2. ❌ 无文件关联: 不支持文件持久化
  3. ❌ 键值管理: 需要管理键值, 可能冲突
  4. ❌ 系统限制: 受系统对共享内存大小、数量限制
  5. ❌ 资源清理: 需要显式删除, 否则会一直占用
  6. ❌ 非 POSIX: System V 特有, 跨平台兼容性差

代码示例对比

相同功能的不同实现

场景: 多进程共享计数器

使用 mmap (文件映射):

// 创建共享文件intfd=open("counter.dat",O_RDWR|O_CREAT,0666);ftruncate(fd,sizeof(int));// 映射int*counter=mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);// 使用(*counter)++;// 清理munmap(counter,sizeof(int));close(fd);unlink("counter.dat");

使用 System V 共享内存:

// 创建共享内存key_tkey=ftok(".",'c');intshmid=shmget(key,sizeof(int),IPC_CREAT|0666);// 附加int*counter=shmat(shmid,NULL,0);// 使用(*counter)++;// 清理shmdt(counter);shmctl(shmid,IPC_RMID,NULL);

功能差异示例

mmap 独有: 文件映射和同步
// mmap 可以映射文件并同步intfd=open("data.txt",O_RDWR);void*addr=mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);// 修改数据strcpy(addr,"Hello");// 同步到文件msync(addr,4096,MS_SYNC);munmap(addr,4096);close(fd);

System V 共享内存不支持文件映射和同步.

System V 共享内存独有: 显式生命周期管理
// System V 共享内存可以独立于进程存在key_tkey=ftok(".",'s');intshmid=shmget(key,4096,IPC_CREAT|0666);// 进程 A 使用void*addr1=shmat(shmid,NULL,0);// ... 使用 ...shmdt(addr1);// 进程 A 退出, 但共享内存段仍然存在// 进程 B 可以继续使用同一个共享内存段void*addr2=shmat(shmid,NULL,0);// ... 使用 ...shmdt(addr2);// 最后删除shmctl(shmid,IPC_RMID,NULL);

mmap 文件映射虽然也持久, 但需要文件存在.

选择建议

选择 mmap 的情况

  1. ✅ 需要文件持久化
  2. ✅ 需要处理大文件(按需加载)
  3. ✅ 需要文件 I/O 和内存访问的统一接口
  4. ✅ 需要跨平台兼容性(POSIX 标准)
  5. ✅ 父子进程通过 fork 共享内存

选择 System V 共享内存的情况

  1. ✅ 纯内存共享, 不需要文件关联
  2. ✅ 需要显式的生命周期管理
  3. ✅ 需要独立于进程存在的共享内存
  4. ✅ 大数据量传输, 性能要求极高
  5. ✅ 不需要按需加载, 内存充足

两者都可以的情况

  • 简单的进程间数据共享
  • 需要零拷贝的高性能通信
  • 多进程共享数据结构

在这种情况下, 可以根据具体需求选择:

  • 如果需要文件持久化 → mmap
  • 如果需要显式生命周期管理 → System V 共享内存
  • 如果需要跨平台 → mmap
  • 如果只需要纯内存共享 → System V 共享内存

总结

mmap 和 System V 共享内存都是高效的进程间通信机制, 两者都实现了零拷贝的直接内存访问. 主要区别在于:

  1. 功能定位: mmap 更通用(文件映射 + 匿名映射), System V 共享内存专门用于 IPC
  2. 内存管理: mmap 支持按需加载, System V 共享内存一次性分配
  3. 持久化: mmap 支持文件持久化, System V 共享内存不支持
  4. API 设计: mmap 统一 API, System V 共享内存专门的 IPC API
  5. 跨平台: mmap 是 POSIX 标准, System V 共享内存是 System V 特有

选择时应该根据具体需求: 需要文件持久化或大文件处理选择 mmap, 需要纯内存共享或显式生命周期管理选择 System V 共享内存.

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 22:58:07

用IXIA IxChariot快速验证SD-WAN性能优化方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个SD-WAN测试配置快速生成器&#xff0c;针对IXIA IxChariot优化。用户输入网络拓扑和业务需求后&#xff0c;自动生成测试脚本和场景配置。支持常见SD-WAN厂商&#xff08;如…

作者头像 李华
网站建设 2026/3/30 5:43:16

SM2加密在政务系统中的应用实践

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个政务文件加密传输演示系统&#xff1a;1. 模拟政府OA系统文件上传流程 2. 使用SM2实现端到端加密 3. 添加数字签名验证 4. 可视化展示加密过程。要求包含前端界面和后端处理…

作者头像 李华
网站建设 2026/3/29 2:56:08

LXMusic1.70音源JS在实际项目中的应用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 在快马平台中生成一个完整的音乐播放器项目&#xff0c;基于LXMusic1.70音源JS。功能包括&#xff1a;播放/暂停、音量控制、音源切换、播放列表管理。要求使用React框架&#xff0…

作者头像 李华
网站建设 2026/4/1 5:27:45

用AI快速开发js for in应用

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个js for in应用&#xff0c;利用快马平台的AI辅助功能&#xff0c;展示智能代码生成和优化。点击项目生成按钮&#xff0c;等待项目生成完整后预览效果 最近在开发一个需要遍…

作者头像 李华
网站建设 2026/3/26 4:50:10

咸鸭蛋变咸的化学奥秘:渗透压原理详解

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个交互式咸鸭蛋科学实验模拟器&#xff0c;可视化展示渗透压原理&#xff1a;1) 3D蛋体结构剖面图显示盐分渗透过程 2) 可调节参数模拟&#xff08;盐浓度15%-30%、温度10-30…

作者头像 李华
网站建设 2026/4/3 4:12:39

TLS协议入门:如何解决版本不匹配问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个交互式TLS协议学习工具&#xff0c;通过简单示例演示TLS协议版本不匹配的问题。工具应提供逐步指导&#xff0c;让用户了解如何检查服务器和客户端的TLS版本&#xff0c;以…

作者头像 李华