news 2026/6/8 8:40:36

Linux系统编程——IPC进程间通信:信号通信与共享内存

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux系统编程——IPC进程间通信:信号通信与共享内存

目录

一、信号通信

1.信号的核心作用

2.信号的发送和接收流程

3.常用信号的默认行为

4.信号相关函数

4.1 发送信号

4.2 捕获信号

二、共享内存

1.共享内存的核心流程

2.共享内存与管道对比

3.共享内存相关函数

3.1 生成唯一键值:ftok ()

3.2 申请共享内存:shmget ()

3.3 映射共享内存到本地:shmat ()

3.4 共享内存的读写操作:memcpy () / strcpy ()

3.5 撤销共享内存映射:shmdt ()

3.6 删除共享内存 / 修改属性:shmctl ()

4.常用命令

三、总结


一、信号通信

1.信号的核心作用

  • 异步通信:不用等对方 “回应”,直接发信号通知
  • 通知机制:处理随机事件(比如程序崩溃、用户中断)

2.信号的发送和接收流程

以 “给 PID=1000 的进程发信号 2(SIGINT)” 为例:

  1. 触发信号:比如终端执行 kill -2 1000
  2. 系统查找进程:Linux 在 PCB(进程控制块)链表中找到 PID=1000 的进程
  3. 中断原流程:暂停进程当前代码,执行 PCB 中信号 2 对应的处理函数(比如 handle2)
  4. 恢复运行:handle2 执行完,进程回到原代码继续运行

Ubuntu 系统中所支持的全部个信号如下:

3.常用信号的默认行为

通过 “man 7 signal” 指令查看:

  • Term:终止进程(比如 SIGINT 信号 2、SIGTERM 信号 15)
  • Core:终止进程并生成核心转储文件(比如 SIGSEGV 信号 11,内存越界)
  • Ign:忽略信号(比如 SIGCHLD 信号17,子进程退出通知)
  • Stop/Cont:暂停 / 恢复进程(比如 SIGSTOP 信号 19)

注意:SIGKILL(信号 9)和SIGSTOP(信号 19)无法被捕获、阻塞或忽略,是强制终止 / 暂停进程的 “终极手段”。

4.信号相关函数

4.1 发送信号

// 函数原型 int kill(pid_t pid, int sig);
  • 功能:通过该函数可以给 pid 进程发送信号为 sig 的系统信号。
  • 参数说明:
    • pid:目标进程 / 进程组的 ID,有 4 种取值方式:
      • pid > 0:发送信号给 PID 为 pid 的单个进程(最常用);
      • pid = 0:发送信号给当前进程所在进程组的所有进程;
      • pid < -1:发送信号给进程组 ID 为 |pid| 的所有进程;
      • pid = -1:发送信号给当前进程有权限发送的所有进程(除 init 进程)。
    • sig:要发送的信号编号(如 2 代表 SIGINT、9 代表 SIGKILL),若 sig = 0 则不发送信号,仅检查目标进程是否存在。
  • 返回值:成功返回 0;失败返回 - 1(并设置 errno,如 ESRCH 表示目标进程不存在,EPERM 表示无权限发送信号)。

4.2 捕获信号

// 函数原型 void (*signal(int signum, void (*handler)(int)))(int); // 简化理解: typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
  • 参数说明:
    • signum:要设置处理方式的信号编号(如 2、9、15);
    • handler:信号处理函数 / 处理方式,有 3 种取值:
      • 自定义函数指针:如 void handle_sigint(int sig),信号触发时执行该函数;
      • SIG_DFL:使用系统默认处理方式(如 SIGINT 默认终止进程);
      • SIG_IGN:忽略该信号(如忽略 SIGCHLD,不处理子进程退出通知)。
  • 返回值:成功返回该信号之前的处理方式(函数指针);失败返回 SIG_ERR(并设置 errno)。
  • 注意:SIGKILL(9) 和 SIGSTOP(19) 无法通过 signal () 修改处理方式。

二、共享内存

1.共享内存的核心流程

步骤:生成键值 → 申请共享内存 → 映射到本地 → 读写数据 → 撤销映射 → 删除共享内存

2.共享内存与管道对比

特性共享内存管道
读写权限双方都可读写半双工(默认单向)
阻塞机制无读 / 写阻塞(需配合信号 / 信号量同步)读空 / 写满会阻塞
数据存储不删除则一直保留数据读取后会被移除
本质内核内存区域(像字符数组)内核缓冲区

3.共享内存相关函数

3.1 生成唯一键值:ftok ()

// 函数原型 key_t ftok(const char *pathname, int proj_id);
  • 功能:通过 pathname 指定的路径,结合 proj_id 生成唯一的临时键值,用于后续申请共享内存。
  • 参数:
    • pathname:任意文件的路径 + 名称,只要该文件不会被删除重建即可;
    • proj_id:整型数字,一般用 ASCII 码的单字符表示,与 pathname 运算生成唯一键值。
  • 返回值:成功返回唯一键值;失败返回 - 1。

3.2 申请共享内存:shmget ()

// 函数原型 int shmget(key_t key, size_t size, int shmflg);
  • 功能:使用唯一键值 key 向内核提出共享内存使用申请。
  • 参数:
    • key:ftok () 生成的唯一键值;
    • size:要申请的共享内存大小;
    • shmflg:申请的共享内存访问权限(八进制表示),搭配宏使用:
      • IPC_CREAT:若共享内存不存在则创建(第一个申请时使用);
      • IPC_EXCL:检测共享内存是否存在,需与 IPC_CREAT 配合使用。
  • 返回值:成功返回共享内存 ID(一般用 shmid 表示);失败返回 - 1。

3.3 映射共享内存到本地:shmat ()

// 函数原型 void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 功能:将指定 shmid 对应的共享内存映射到本地内存,让进程能直接访问。
  • 参数:
    • shmid:要映射的共享内存 ID;
    • shmaddr:本地可用的地址,不确定则设为 NULL(由系统自动分配);
    • shmflg:
      • 0:表示对共享内存有读写权限;
      • SHM_RDONLY:表示仅只读权限。
  • 返回值:成功返回映射的地址(一般等于 shmaddr);失败返回 (void*)-1。

3.4 共享内存的读写操作:memcpy () / strcpy ()

映射完成后,可通过常规内存操作函数读写共享内存:

  • memcpy():用于二进制对象的读写;
  • strcpy():用于字符串对象的读写。

3.5 撤销共享内存映射:shmdt ()

// 函数原型 int shmdt(const void *shmaddr);
  • 功能:将本地内存与共享内存断开映射关系。
  • 参数:shmaddr:shmat () 返回的映射地址。

3.6 删除共享内存 / 修改属性:shmctl ()

// 函数原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 功能:修改共享内存属性,或删除指定的共享内存对象。
  • 参数:
    • shmid:要操作的共享内存 ID;
    • cmd:操作指令,设为 IPC_RMID 表示删除共享内存对象;
    • buf:设为 NULL 表示仅执行删除操作(无需获取 / 修改共享内存属性)。
  • 返回值:成功返回 0;失败返回 - 1。

4.常用命令

  • 查看 IPC 资源:ipcs -a(能看共享内存、信号量、消息队列)
  • 删除共享内存:ipcrm -m shmid(通过 shmid 删除指定共享内存)

三、总结

  1. 信号核心函数:kill()(发信号)、signal()(处理信号),且 SIGKILL / SIGSTOP 无法被捕获 / 忽略;
  2. 共享内存核心流程是 “生成键值→申请→映射→读写→撤销映射→删除”,核心函数为 ftok()、shmget()、shmat()、shmdt()、shmctl();
  3. 共享内存无天然阻塞 / 同步机制,需配合信号 / 信号量保证数据读写安全。通过 shmid 删除指定共享内存)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/2 11:34:16

rusefi:免费开源ECU平台,让汽车控制更智能

rusefi是一个基于GPL许可证的开源ECU&#xff08;电子控制单元&#xff09;项目&#xff0c;为汽车爱好者、工程师和开发者提供完整的发动机控制系统解决方案。无论您是想进行汽车ECU改装、学习发动机控制单元开发&#xff0c;还是构建原型系统&#xff0c;rusefi都能为您提供强…

作者头像 李华
网站建设 2026/6/7 17:24:28

小鼠大脑立体定位图谱终极指南:从零基础到精准定位的完整教程

小鼠大脑立体定位图谱终极指南&#xff1a;从零基础到精准定位的完整教程 【免费下载链接】小鼠大脑立体定位图谱资源文件介绍 《小鼠大脑立体定位图谱》是一本由澳大利亚新南威尔士大学Paxinos教授编写的权威解剖图谱&#xff0c;填补了国内小鼠脑组织解剖资源的空白。本书包含…

作者头像 李华
网站建设 2026/6/8 5:08:45

Flutter广告监测终极方案:用AdSpark Pro构建精准归因与增长引擎

你是否曾因广告数据黑洞而错失增长良机&#xff1f;是否在复杂的渠道归因中迷失方向&#xff1f;作为移动应用开发者&#xff0c;我们深知广告效果追踪的痛点。本文将为你揭示三步构建精准归因体系的完整方案&#xff0c;让每一分广告投入都产生可衡量的回报。 【免费下载链接】…

作者头像 李华
网站建设 2026/6/6 22:47:26

3大Python开源项目终极对决:谁才是你的最佳选择?

还在为选择Python开源项目而烦恼&#xff1f;面对众多功能强大的应用&#xff0c;你是否常常感到无从下手&#xff1f;Home Assistant、Calibre和Django三大明星项目各有千秋&#xff0c;本文将从实际使用场景、技术门槛、扩展性等多个维度为你深度解析&#xff0c;帮你找到最适…

作者头像 李华
网站建设 2026/6/6 22:23:06

Langchain-Chatchat矿业安全规程:井下作业标准操作指引

Langchain-Chatchat矿业安全规程&#xff1a;井下作业标准操作指引 在煤矿、金属矿等地下作业环境中&#xff0c;安全规程的执行直接关系到一线工人的生命安危。然而现实中&#xff0c;面对厚厚一叠《煤矿安全规程》或《动火作业审批流程》&#xff0c;即便是经验丰富的安全员也…

作者头像 李华