Linux系统编程|进程间通信IPC全套详解(1)(管道、信号)

一、管道通信

管道本质是内核开辟的一块缓冲区,遵循FIFO先进先出规则,分为无名管道pipe和有名管道FIFO(mkfifo)。

1.1 无名管道(匿名管道 pipe)

无名管道只能用于有亲缘关系进程之间通信(父子、兄弟进程)。

原理:父进程调用`pipe()`创建管道得到两个文件描述符,fork创建子进程后,子进程复制父进程文件描述符,父子进程就可以操作同一组管道fd完成数据传输。

函数原型

#include <unistd.h>

int pipe(int pipefd2);

  • pipefd0:管道读端,使用read读取数据

  • pipefd1:管道写端,使用write写入数据

  • 返回值:成功返回0;失败返回1

管道核心特性

  1. 半双工单向通信;数据只能单向流动;

  2. 缓冲区默认大小64K;

  3. 写阻塞:管道写满,write会阻塞;

  4. 读阻塞:管道为空,read会阻塞;

  5. 读返回0:管道写端全部关闭,read返回0,代表读到末尾;

  6. 管道破裂SIGPIPE:管道读端全部关闭,继续写管道,会产生SIGPIPE信号,进程默认直接退出。

简单示例逻辑:父进程创建pipe,fork子进程;父关闭读端往pipefd1写数据;子关闭写端从pipefd0读数据。

1.2 有名管道 FIFO(mkfifo)

无名管道局限于亲缘进程,有名管道解决这个问题,可以用于本机任意两个进程通信。

它会在文件系统生成一个特殊管道文件,不同进程通过open打开这个文件,就可以完成通信。

函数原型

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

  • pathname:管道文件路径

  • mode:文件权限,例如0664

  • 返回值:成功0,失败1

创建完成后,就像普通文件一样使用open/read/write/close操作。

注意:打开FIFO会发生阻塞:一个进程以读打开,会阻塞等待另一个进程以写打开;反之亦然。

无名管道 vs 有名管道对比

|------------|-------------------|-------------------|
| 特性 | 无名管道 pipe | 有名管道 FIFO |
| 适用进程 | 仅父子 / 兄弟亲缘进程 | 本机任意进程 |
| 文件系统 | 无实体文件,内核缓冲区 | 生成 FIFO 特殊文件 |
| 创建方式 | pipe() | mkfifo() |
| 生命周期 | 进程全部退出自动销毁 | 文件存在,可手动 rm 删除 |

二、信号 Signal ------ 异步软中断通知

信号是Linux提供的异步通知机制,信号本身不携带大量业务数据,仅仅用来通知进程发生某个事件,相当于软件层面的中断。

常见信号列表

|--------------|-----------------|------------------------|
| 信号编号 | 宏名称 | 作用说明 |
| 2 | SIGINT | Ctrl+C,中断进程 |
| 3 | SIGQUIT | Ctrl+\,进程退出 |
| 9 | SIGKILL | 强制杀死进程,不能捕获、不能忽略 |
| 11 | SIGSEGV | 段错误,访问非法内存触发 |
| 13 | SIGPIPE | 管道破裂,写已经没有读端的管道 |
| 14 | SIGALRM | alarm 定时超时信号 |
| 17 | SIGCHLD | 子进程退出时,发送给父进程,用来回收僵尸进程 |
| 19 | SIGSTOP | 强制暂停进程,不可捕获忽略 |
| 10/12 | SIGUSR1、SIGUSR2 | 用户自定义预留信号,业务自己使用 |

信号三种处理方式

进程收到信号,可以选择下面三种处理:

  1. SIG_IGN 忽略:收到信号直接无视,不做处理

  2. SIG_DFL 默认处理:操作系统默认行为(终止、暂停、打印core转储等)

  3. 捕获信号:注册自定义处理函数,收到信号执行自己写的回调函数

signal注册信号函数

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

  • signum:要处理的信号编号

  • handler:处理方式,SIG_IGN / SIG_DFL / 自定义回调函数地址

  • 返回值:成功返回旧处理函数;失败返回SIG_ERR

注意:signal函数接口简单,但部分行为在不同版本Linux存在差异;正式项目推荐使用sigaction。

简单示例:捕获Ctrl+C信号,不直接杀死程序

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

void sig_handler(int sig)

{

printf("收到信号 %d,程序不会直接退出\n", sig);

}

int main(void)

{

signal(SIGINT, sig_handler);

while(1)

{

sleep(1);

printf("程序运行中...\n");

}

return 0;

}

相关推荐
Tel199253080045 分钟前
温度湿度信号转WiFi/MQTT/Modbus TCP采集模块 无线传输
网络·网络协议·tcp/ip·工业自动化·工控设备
DigitalOcean14 分钟前
不受限于 Copilot,教你在 VS Code 中接入 GPT、Claude
agent·visual studio code
迪菲赫尔曼16 分钟前
【基础篇 12】把环境与源码接起来:检查 GPU,再安装服务器上的项目
运维·服务器·开发语言·人工智能·python·yolo·目标检测
cq林志炫26 分钟前
两个Linux服务器之间同步文件
linux·运维·服务器
2601_9628857232 分钟前
2026 Python 股票数据接口选型指南(横评 + 决策树)
开发语言·python·区块链
yyuuuzz1 小时前
云服务器安全组规则优先级的机制记录
运维·服务器·网络·安全·阿里云·aws
Evand J1 小时前
【PMSM例程4】PMSM电阻辨识与模型补偿EKF,MATLAB例程。附下载链接,包运行成功
开发语言·matlab·电机·ekf·卡尔曼·pmsm
王仔小奶1 小时前
Rust 正在接管金融圈?深度拆解一份高薪 FinTech 岗位 JD
开发语言·金融·rust
小王C语言1 小时前
Qt常用控件:多元素控件,纵向列表,表格控件,树状控件
开发语言·qt
fanruitian1 小时前
python 可视化 panda seaborn matplotlib.pyplot
开发语言·python·matplotlib