news 2026/5/1 9:18:34

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/23 9:51:34

【课程设计/毕业设计】基于SpringBoot的智慧医疗微信小程序的设计与实现基于springboot+微信小程序的智能医疗管理系统设计与实现【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/1 6:09:41

【课程设计/毕业设计】基于springboot+vue的微信小程序的大学生校园生活系统的设计与实现基于springboot+微信小程序的校园活动管理系统设计与实现【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/1 7:58:13

零基础学IP管理:从概念到实战第一课

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个交互式IP地址学习工具&#xff0c;包含&#xff1a;1. IP地址基础知识讲解区&#xff08;IPv4/v6、子网划分等&#xff09;2. 可视化练习区&#xff08;通过拖拽方式配置虚…

作者头像 李华
网站建设 2026/5/1 7:56:46

Endus v1.0.1 – 现代优雅工业制造 WordPress 网站主题

Endus 是一个工业制造 WordPress 主题。这是一个现代、美丽、优雅的工业制造主题。你可以根据喜好更改所有部分。有定制选项&#xff0c;每个部分都独具创意&#xff0c;专为工业制造服务设计。它拥有独特的设计和惊人的功能&#xff0c;适合想要建立网站的工业制造服务。我们构…

作者头像 李华
网站建设 2026/4/30 10:42:46

用foreach快速构建数据处理原型:3个实用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个基于foreach的快速数据处理原型生成器。用户可以选择数据类型(CSV/JSON/数组)和处理需求(过滤/转换/聚合)&#xff0c;系统自动生成使用foreach的实现代码。功能包括&#…

作者头像 李华
网站建设 2026/5/1 7:57:47

企业级Maven配置实战:从安装到多环境部署

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个企业级Maven配置演示项目&#xff0c;包含&#xff1a;1.本地仓库与Nexus私服配置 2.多环境profile配置(dev/test/prod) 3.父子模块依赖管理 4.Jenkins集成配置 5.代码质量…

作者头像 李华