跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C

Linux 共享内存实现进程间高效数据传输

介绍 Linux 共享内存作为进程间通信的高效方式。涵盖核心概念、工作流程及关键函数(ftok、shmget、shmat、shmdt、shmctl)。详细说明了共享内存的申请、挂载、读写、解绑与销毁步骤,并解释了互斥、临界资源及信号量在保障数据一致性中的作用。适合需要夯实 Linux 系统编程基础的开发者。

暖阳发布于 2026/3/27更新于 2026/9/1065 浏览
Linux 共享内存实现进程间高效数据传输

Linux 共享内存介绍

共享内存属于一种进程通信方式,让多个进程通过访问同一块内存实现通信。

文章配图

整体流程与特点

流程

总的流程分为以下几步:已存在的共享内存通过 Key 直接用即可,不用重新申请。

文章配图

需要先申请共享内存,然后与它建立联系,不想用了就去除关联,最后看情况释放共享内存即可。

特点

  1. 共享内存申请之后,如果不主动释放,那它就会等到系统关闭才主动释放。
  2. 共享内存的通信不会出现阻塞的情况(这是较于两种管道通信最大的区别)。即:可以同时实现数据写入,A 进程不用阻塞等待 B 进程。
  3. 通信成功的关键是:读写双方必须约定相同的数据类型和解析规则。例如:A 以字符串写入,B 就以字符串读取,如果 B 是整型读取,就会出现乱码。
  4. 共享内存的释放:由创建者销毁,且创建者标记'销毁'之后,也会等失去所有挂载连接之后才会释放这块共享内存。下面是指令版的查看共享内存和销毁:

ipcs -m 查看所有存在的共享内存

ipcrm -m "共享 ID" 手动直接销毁该共享内存

使用步骤

1. 申请共享内存

共享内存的申请涉及到两个函数:ftok() 与 shmget()。

1. ftok()

函数原型:

#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

参数:都是自定义的,系统会根据它们调用算法形成唯一的 Key,这个 Key 是较于操作系统的。(只要这两个参数相同,就会生成相同的 Key->进而找到同一块共享内存)

返回值:

  • 成功:返回一个 key_t 类型的整数(就是生成的'唯一编号')
  • 失败:返回 -1(比如路径不存在,或权限不够)

作用:生成'唯一标识'较于系统的钥匙 Key。

2. shmget()

函数原型:

#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

参数: 第一个参数:通过调用 ftok() 获取的较于操作系统的 Key。 第二个参数:你理想的共享内存大小(每次最好是 4KB,因为'块'以'4KB'为整数标准)。 第三个参数:操作标志(权限 + 行为),常用组合:(使用新内存或者旧内存!)

  • IPC_CREAT | 0666:如果 key 对应的共享内存不存在,就新建一个,权限设为 666(所有人可读写,类似文件权限)
  • IPC_EXCL | IPC_CREAT:如果共享内存已存在,就报错(确保一定是新建的,避免误操作已有内存)
  • 单独传 0:只查找已存在的共享内存,不新建

作用:生成'唯一标识'较于用户的钥匙 ID(其实也算'Key',只是对于用户层面的)。

返回值:

  • 成功:返回一个'共享内存 ID'(非负整数,后续操作共享内存都用这个 ID)
  • 失败:返回 -1(比如权限不够、内存不足、key 不存在且没加 IPC_CREAT)

2. 挂接

挂接:与该共享内存建立联系,比如你想怎么使用,需要用到接口(shmat())。

函数原型:(需要强转)

#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

参数: 第一个参数:'共享内存 ID'。 第二个参数:告诉操作系统挂载到共享内存的哪个地方,一般推荐 NULL 参数。 第三个参数:挂载权限,一般选择 0(可读可写)。

返回值:

  • 成功:返回共享内存在当前进程地址空间中的实际挂载地址(void*类型,可直接作为指针使用)
  • 失败:-1(可以通过检查 errno 获取错误原因,如地址冲突、权限不足等)

作用:搭建'窗口',真正使用共享内存。

3. 去关联

即失去与该共享内存的关联,代表不再使用它。

函数原型:

#include <sys/shm.h>
int shmdt(const void *shmaddr);

参数:通过 shmat() 挂接该共享内存的指针。

返回值:

  • 成功:返回 0(表示已成功解除关联)
  • 失败:返回 -1(可通过 errno 查看错误原因,例如 shmaddr 不是有效的挂载地址、权限不足等)

作用:失去与该共享内存的关联。

4. 释放共享内存

函数原型:

#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

参数: 第一个参数:'共享内存 ID'。 第二个参数:对共享内存执行的操作(我们暂时学习两个即可)。

命令作用
IPC_STAT读取共享内存的状态信息,存储到 buf 指向的 struct shmid_ds 结构体中
IPC_RMID标记共享内存为'待销毁',当所有进程都卸载后,内核会彻底删除它

第三个参数: buf 是一个指向 struct shmid_ds 类型的指针,该结构体用于存储或设置共享内存的详细信息。

  • 当 cmd=IPC_STAT 时:buf 用于接收状态(内核会将共享内存的信息写入 buf)
  • 当 cmd=IPC_RMID 时:buf 无用,通常传 NULL 即可

返回值:

  • 成功:返回 0(无论执行哪种 cmd,成功均返回 0)
  • 失败:返回 -1(可通过 errno 查看错误原因,如权限不足、shmid 无效等)

作用:对共享内存执行的操作。

5. 示例

我们将 Key 的获取封装一下:

const char* ptr_ftok="Hello Linux";
const int pid_ftok = 1024;

文章配图

创建共享内存:此处省略相关判断逻辑。

文章配图

使用共享内存:此处省略相关判断逻辑。

文章配图

共享内存效率与内核

为何是这样?共享内存与文件描述表都是在进程地址空间上的,可以直接跳过文件表访问共享内存。

文章配图

信号量与高效

什么是'互斥'?

当共享内存被两个进程访问时,如果 A 需要持续写入 3 秒的数据,但是 B 进程在二秒的时候就进行了读取,这就导致通信结果不理想,因此为了避免这种情况,任何时刻,只能一个进程(属于执行流)访问该共享资源。

什么是'临界资源'?

被多个执行流(进程、线程)都能访问的共享资源,而这些资源,通常是代码、数据。

什么是'临界区'?

简单来说:临界区就是执行流正在访问共享资源中的代码数据。

因此就算有 100 行代码在'临界资源',但是被访问的那 5 行才叫临界区。

什么是'信号量'?

信号量是一个计数器,来记录该'临界资源'还可以被多少执行流访问,通常执行两个操作:

'P'操作:有执行流访问临界资源,计数 -1

'V'操作:该执行流退出访问临界资源,计数器 +1

什么是'原子性'?

'原子性'是较于'P'和'V'操作的执行特性:要么不执行,要么执行完。

什么是'二元信号量'?

如果信号量的计数器只能是 0(资源无法使用)或 1(可使用),更像资源的使用状态!

**效率:**信号量(可调用共享资源的执行流数量)+'原子性'——便形成了'互斥',共享访问达成高效。

(注:'信号量'的学习与后面的'信号'无关)

目录

  1. Linux 共享内存介绍
  2. 整体流程与特点
  3. 流程
  4. 特点
  5. 使用步骤
  6. 1. 申请共享内存
  7. 1. ftok()
  8. 2. shmget()
  9. 2. 挂接
  10. 3. 去关联
  11. 4. 释放共享内存
  12. 5. 示例
  13. 共享内存效率与内核
  14. 信号量与高效

更多推荐文章

查看全部
  • Android 热修复原理与 HotFix 框架实现详解
  • 机场出租车调度问题数学建模实战解析(含 Python 模拟代码)
  • 2024 年大语言模型(LLM)微调方法全面总结
  • 三数之和:C 语言双指针解法详解
  • Neo4j 数据库连接失败排查与修复指南
  • Trae IDE 核心机制拆解:AI Agent 中 Skill 的定义与功能实现
  • 华为 OD 技术面:C++ 核心八股题解析
  • 前端流式输出实现详解:从原理到实践
  • 前端权限控制设计:告别硬编码判断
  • MySQL 常用函数整理与使用指南
  • Spring AOP 切入点表达式解析及多条件组合技巧
  • Git 版本管理工具基础使用指南
  • 基于姓名的日本族裔身份算法判定:数字人文实践解读
  • 相干伊辛机在医疗及医疗 AI 领域的应用前景
  • AI 大模型对网络的五大需求及技术应对方案
  • Yolo11 基于DroneVehicle数据集的无人机视角下车辆目标检测
  • LeetCode Hot 100 贪心算法详解
  • Windows 家用电脑部署 Gemma3 大模型:Ollama+Open WebUI 搭建 AI 聊天室
  • OpenClaw 零成本部署指南:基于 GitHub Codespaces 与 Discord
  • AI 提示词重构建议:提升代码可读性的实战指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online