仅限Pro订阅者可见的调色板隐藏指令集(含--palette-hex、--chroma-lock、--gamut-clamp三重锁色协议)
2026/5/23 22:25:01
mmap 和 System V 共享内存都是 Linux 中用于进程间通信(IPC)的机制, 两者都允许多个进程共享同一块物理内存, 实现零拷贝的高效通信. 本文档从使用方式、特点、实现机制等多个维度进行详细对比.
#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);特点:
#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);特点:
文件映射方式:
// 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);// 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);| 特性 | mmap | System V 共享内存 |
|---|---|---|
| 标识方式 | 文件路径 + 文件描述符 | 键值(key) + shmid |
| 键值生成 | 不需要(使用文件路径) | 需要ftok()或IPC_PRIVATE |
| 跨进程共享 | 通过文件路径 | 通过键值 |
| 持久性 | 文件映射持久, 匿名映射不持久 | 显式删除前持久 |
| 特性 | mmap | System V 共享内存 |
|---|---|---|
| 文件关联 | 可以映射文件, 也可以匿名映射 | 不关联文件, 纯内存 |
| 持久性 | 文件映射持久, 匿名映射不持久 | 显式删除前持久 |
| 同步到文件 | 支持msync()同步到文件 | 不支持文件同步 |
| 按需加载 | 支持, 利用虚拟内存按需加载 | 不支持, 一次性分配 |
| 大文件处理 | 适合处理大文件 | 不适合, 需要一次性分配全部内存 |
| 灵活性 | 高, 可以映射文件、设备、匿名区域 | 中, 只能创建纯内存段 |
| 地址选择 | 可以指定地址或让系统选择 | 可以指定地址或让系统选择 |
| 性能指标 | mmap | System V 共享内存 |
|---|---|---|
| 零拷贝 | ✅ 是 | ✅ 是 |
| 直接内存访问 | ✅ 是 | ✅ 是 |
| 延迟 | 低(直接内存访问) | 极低(直接内存访问) |
| 吞吐量 | 高(零拷贝) | 极高(零拷贝) |
| CPU占用 | 低 | 低 |
| 内存占用 | 按需加载, 节省内存 | 一次性分配, 占用固定内存 |
| 缺页处理 | 支持, 按需加载文件内容 | 不支持, 内存已分配 |
两者都需要用户空间的同步机制:
| 同步机制 | mmap | System V 共享内存 |
|---|---|---|
| 内核保护 | ❌ 无 | ❌ 无 |
| 需要同步 | ✅ 是 | ✅ 是 |
| 常用同步方式 | 信号量、互斥锁、原子操作 | 信号量、互斥锁、原子操作 |
| 同步复杂度 | 相同 | 相同 |
核心数据结构:
vm_area_struct(VMA): 虚拟内存区域描述符mm_struct: 进程地址空间描述符file: 文件对象(文件映射时)实现路径:
sys_mmap2 → do_mmap_pgoff → - 地址选择(get_unmapped_area) - VMA 创建和初始化 - 文件映射(file->f_op->mmap) 或匿名映射(shmem_zero_setup) - VMA 插入到进程地址空间关键特点:
核心数据结构:
shmid_kernel: 共享内存段描述符shmem_inode_info: shmem 文件系统 inodekern_ipc_perm: IPC 权限和键值管理实现路径:
sys_shmget → newseg → - 创建 shmid_kernel - 创建 shmem 文件(shmem_file_setup) - 安装到 IPC ID 表 sys_shmat → do_shmat → - 权限检查 - 调用 do_mmap_pgoff 映射 shm_file - 更新附加计数关键特点:
| 方面 | mmap | System V 共享内存 |
|---|---|---|
| 内存分配时机 | 按需分配(缺页时) | 创建时一次性分配 |
| 物理页管理 | 页缓存或匿名页 | shmem 文件系统页 |
| 换入换出 | 支持(除非 MAP_LOCKED) | 支持(除非 SHM_LOCK) |
| 内存锁定 | MAP_LOCKED 标志 | SHM_LOCK 命令 |
| 页表管理 | 通过 VMA 管理 | 通过 VMA 管理(内部使用 mmap) |
| 特性 | mmap | System V 共享内存 |
|---|---|---|
| 文件系统 | 文件映射依赖文件系统, 匿名映射使用 shmem | 内部使用 shmem, 用户不可见 |
| 文件可见性 | 文件映射时文件可见 | 文件不可见(内部使用) |
| 文件同步 | 支持 msync 同步到文件 | 不支持文件同步 |
✅适合:
❌不适合:
✅适合:
❌不适合:
优点:
缺点:
优点:
缺点:
使用 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 可以映射文件并同步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 共享内存可以独立于进程存在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 和 System V 共享内存都是高效的进程间通信机制, 两者都实现了零拷贝的直接内存访问. 主要区别在于:
选择时应该根据具体需求: 需要文件持久化或大文件处理选择 mmap, 需要纯内存共享或显式生命周期管理选择 System V 共享内存.