Linux 进程间通信学习笔记

一、进程间通信 5 种方式

  1. 管道(无名管道、有名管道 FIFO)
  2. 信号
  3. 消息队列
  4. 共享内存
  5. 信号灯(信号量)

进程之间互相隔离,各自有独立地址空间,不能直接访问对方内存,必须依靠内核提供的机制完成数据交互。

1. 管道

1.1 无名管道 pipe

  • 限制:只支持有亲缘关系的进程通信(父子、兄弟进程)
  • 函数原型
c 复制代码
int pipe(int pipefd[2]);
  • 参数
    • pipefd[0]:读端文件描述符
    • pipefd[1]:写端文件描述符
  • 返回值:成功返回 0,失败返回 -1
无名管道核心特性(考试重点)
  1. 管道有写端
    • 管道里面有数据,直接读取数据
    • 管道无数据,读操作阻塞等待,直到有数据写入
  2. 管道没有写端(写端全部关闭)
    • 管道有数据直接读;没有数据,read 直接返回 0,不阻塞
  3. 管道有读端
    • 管道没写满(默认 64K 缓冲区),直接写入
    • 管道写满,write 阻塞,等待读端读走数据之后才能继续写
  4. 管道没有读端(所有读端关闭)
    • 执行 write 写数据,触发管道破裂 SIGPIPE 信号,进程直接退出。

无名管道是半双工:一端读、一端写,单向数据流。

1.2 有名管道 FIFO mkfifo

  • 突破无名管道限制:任意两个进程之间都可以通信,不需要亲缘关系
  • 特性:读写两端必须都打开,程序才会往下执行;只打开一端,程序阻塞等待另一端打开。

函数接口

c 复制代码
int mkfifo(const char *pathname, mode_t mode);
  • pathname:管道文件路径名
  • mode:文件权限
  • 返回值:成功 0,失败 -1

练习:写 read.c 和 write.c,实现两个程序聊天。

write.c 接收终端输入发给 read.c;read.c 接收打印,再把内容回传给 write.c。

2. 信号

信号是内核层给应用层进程发送通知的机制,属于异步通信。进程不知道信号什么时候到来。

进程收到信号三种处理方式

  1. 缺省 SIG_DFL:系统默认行为(大部分信号默认杀死进程)
  2. 忽略 SIG_IGN:收到信号直接无视,什么都不干
  3. 捕捉:注册自定义处理函数,信号来了执行自己写的回调函数

常用信号记忆表格

信号 触发来源 作用
SIGINT Ctrl + c 中断进程
SIGQUIT Ctrl + \ 退出进程
SIGKILL(9) kill -9 强制杀死,不能忽略、不能捕捉
SIGSEGV 程序内部 段错误
SIGPIPE 管道写操作 管道破裂
SIGALRM alarm() 定时时间到达
SIGCHLD 子进程 子进程结束通知父进程
SIGCONT 唤醒继续运行暂停进程
SIGSTOP(19) 暂停进程,不能忽略、不能捕捉
SIGTSTP Ctrl + z 挂起暂停
SIGIO 异步 IO 通知

重点:9 号 SIGKILL、19 号 SIGSTOP,不能忽略、不能捕捉,无法被程序拦截。

信号函数接口

signal() 注册信号处理函数
c 复制代码
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
  • signum:信号编号
  • handler:
    • SIG_IGN:忽略信号
    • SIG_DFL:恢复系统默认处理
    • 自定义函数地址:捕捉信号,信号到来调用该函数
  • 返回值:成功返回上一次注册的处理函数地址;失败返回 SIG_ERR
pause()
c 复制代码
int pause(void);

功能:让进程休眠阻塞,直到收到信号才唤醒。

alarm() 闹钟
c 复制代码
unsigned int alarm(unsigned int seconds);

seconds 秒之后,内核给当前进程发送 SIGALRM 闹钟信号。

📝 学习复盘 & 踩坑总结

  1. 无名管道只能亲缘进程;有名管道 FIFO 任意进程都能用。
  2. 管道破裂:写管道,但是所有读端全部关闭 → SIGPIPE 信号,进程直接死掉。写代码必须注意。
  3. 信号是异步!进程不知道信号什么时候来。9、19 号信号不受程序控制。
  4. pipe 创建出来两个 fd,fork 之后子进程会复制文件描述符,父子各持有读写两端,记得不用的一端 close 关闭。
  5. pause 会一直睡,只有信号到来才会解除阻塞。
相关推荐
沫璃染墨几秒前
从零入门计算机网络系列(十一):HTTP协议进阶——从重定向原理到GET/POST与Fiddler抓包
linux·服务器·开发语言·网络·c++·tcp/ip·html
蓝祁子yoky1 小时前
Qt学习日记 Day13:网络编程(一)-TCP基础与Socket实战
网络·qt·学习
箓维1 小时前
TCP Socket的进阶实现
网络·笔记·tcp/ip
二哈赛车手1 小时前
新人笔记---hermes定时功能设计,具体讲解以及可优化点
java·人工智能·笔记·spring·ai·typescript
架构师伯子明2 小时前
Ros 学习十三:IK Demo
学习
AI_Lab012 小时前
宝塔用了两年,有没有必要换成轻量方案?
linux·运维·服务器
by209992 小时前
Linux GDB 调试与 CGDB 使用
linux·运维·服务器·经验分享
小羊没烦恼!2 小时前
关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
java·服务器·网络·学习·负载均衡
幼儿园蛋小黄2 小时前
从 STM32N647 的 AI 部署入门嵌入式:一条可落地的学习路线
人工智能·stm32·学习
星恒随风2 小时前
Linux网络编程:应用层协议究竟是什么?从网络计算器到TCP Socket抽象基类完整实现
linux·网络·笔记·tcp/ip