【Note】《深入理解Linux内核》 第十九章:深入理解 Linux 进程通信机制

《深入理解Linux内核》 第十九章:深入理解 Linux 进程通信机制(Process Communication)

关键词:IPC、信号、管道、FIFO、消息队列、信号量、共享内存、套接字、内核对象、同步机制


一、进程通信概述

1.1 为什么需要进程通信

在 Linux 系统中,进程是资源隔离的基本单位,彼此间通常无法直接访问彼此的地址空间。因此需要一套机制,使得多个进程之间可以:

  • 交换数据
  • 同步行为
  • 发送通知
  • 共享资源

这些功能由 Linux IPC(Inter-Process Communication)子系统实现。

1.2 IPC 分类

类型 描述
信号 最基本的异步通知机制
管道/FIFO 字节流通信机制,面向数据流
消息队列 面向结构化消息,先进先出
信号量 同步与互斥,典型用于资源控制
共享内存 多进程映射同一段内存,效率最高
套接字 网络与本地通信统一抽象,支持多协议

二、信号(Signal)

2.1 概述

信号是进程间最早被引入的通信机制,本质上是一个异步事件通知。

示例信号 描述
SIGINT 中断(Ctrl+C)
SIGTERM 终止进程请求
SIGKILL 无条件终止进程(不可捕获)
SIGCHLD 子进程结束通知父进程

2.2 信号相关系统调用

  • kill(pid, sig):向指定进程或进程组发送信号;
  • signal(sig, handler):设置信号处理函数;
  • sigaction():更强大的信号控制;
  • sigprocmask():阻塞/允许某些信号;
  • sigqueue():带参数的信号发送。

2.3 内核实现

  • 每个进程结构 task_struct 中包含 sigpendingsignal 字段;
  • 信号通过 do_signal() 派发;
  • 某些信号是不可忽略/不可屏蔽的(如 SIGKILL);
  • Linux 通过实时信号(SIGRTMIN ~ SIGRTMAX)支持有序队列与附加参数。

三、管道与 FIFO

3.1 管道(pipe)

管道是最基本的 IPC 数据流机制,数据在两个进程间以 FIFO 形式流动。

c 复制代码
int pipe(int pipefd[2]); // pipefd[0]=read, pipefd[1]=write

特点:

  • 半双工(单向通信);
  • 父子进程间常见用途;
  • 基于内核中的 pipe_inode_info 结构实现;
  • 使用缓冲区环形队列实现数据传输。

3.2 命名管道(FIFO)

可跨进程、不限于亲缘关系:

bash 复制代码
mkfifo /tmp/myfifo

特点:

  • 是一种特殊文件;
  • 可在 shell 中使用 < /tmp/myfifo> /tmp/myfifo

3.3 内核实现

  • 管道是内核中一种特殊的字符设备;
  • 每个 pipe 被表示为一个 inode;
  • 内核用 struct pipe_inode_info 管理缓冲区、读写端等。

四、消息队列(Message Queues)

4.1 概述

消息队列允许进程以"消息"为单位进行通信,每条消息是结构化数据(类型 + 数据内容)。

c 复制代码
int msgget(key_t key, int msgflg);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

4.2 内核数据结构

c 复制代码
struct msg_queue {
    struct list_head q_messages;
    ...
};
  • 所有消息链入 q_messages
  • 支持按类型匹配接收;
  • 消息大小有限制(msgmax)。

4.3 特点

  • 支持异步发送、同步接收;
  • 按优先级接收;
  • 属于 System V IPC 之一;
  • 支持权限与 quota 控制。

五、信号量(Semaphores)

5.1 概述

信号量提供一种同步机制,用于控制多个进程对共享资源的访问,支持阻塞和非阻塞操作。

c 复制代码
int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, size_t nsops);
  • 每个信号量集合由 semid 索引;
  • semop() 支持加锁/解锁操作(P/V操作);
  • 使用计数表示资源状态。

5.2 内核结构

c 复制代码
struct sem_array {
    struct sem *sem_base;
    ...
};
  • Linux 信号量集支持原子操作;
  • 支持 undo 机制,在进程终止时自动释放资源;
  • 属于 System V IPC 范畴,现代内核中逐渐被 futex 和 pthread 替代。

六、共享内存(Shared Memory)

6.1 概述

多个进程将一段物理内存映射到各自虚拟地址空间,实现高效通信。

c 复制代码
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

特点:

  • 速度最快的 IPC;
  • 通常配合信号量/互斥锁使用;
  • 属于 System V IPC;

6.2 内核实现

  • 使用 shmid_kernel 描述共享段;
  • 实质上是内核为各进程映射同一段物理页;
  • 页表项被多个进程共享;
  • 写时复制(COW)策略在此无效。

七、套接字通信(Socket)

7.1 套接字种类

类型 描述
UNIX 域套接字 仅限本机通信,文件系统路径寻址
INET 套接字 网络通信,使用 IP 与端口
STREAM 面向连接,类似 TCP
DGRAM 无连接,类似 UDP

7.2 创建通信过程

c 复制代码
int socket(int domain, int type, int protocol);
int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, struct sockaddr *addr, socklen_t addrlen);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • socket 通信是最通用的进程通信方式;
  • 在内核中通过 sock 结构表示;
  • 数据缓冲使用 sk_buff 结构管理。

八、Linux IPC 统一接口

Linux 提供 /proc/sysvipc/ 系统接口与 ipcs 工具来统一查看 IPC 对象:

bash 复制代码
ipcs -m   # 共享内存
ipcs -q   # 消息队列
ipcs -s   # 信号量

可以使用 ipcrm 删除对象。


九、IPC 命名空间与隔离(Namespace)

9.1 IPC Namespace

每个 IPC 对象(shm、sem、msg)都可以在命名空间中隔离,容器技术(如 Docker)广泛使用。

  • 创建 IPC namespace:unshare --ipc
  • 每个命名空间有独立的 IPC 资源空间;
  • 安全、稳定、互不干扰。

十、内核源码参考路径

文件路径 作用描述
kernel/signal.c 信号实现与分发
ipc/msg.c 消息队列实现
ipc/sem.c 信号量实现
ipc/shm.c 共享内存实现
fs/pipe.c 管道与 FIFO 实现
net/unix/af_unix.c UNIX 域 socket 实现
include/linux/ipc_namespace.h IPC 命名空间
include/linux/shm.h 共享内存头文件

十一、小结

  • Linux 提供多种 IPC 机制,各有优缺点与适用场景;
  • 信号适合简单事件通知;
  • 管道与 FIFO 适合流式数据传输;
  • 消息队列支持结构化数据传递;
  • 信号量用于同步资源控制;
  • 共享内存效率最高,但需额外同步手段;
  • 套接字最通用,跨主机通信也适用;
  • IPC 命名空间提升系统隔离性与安全性。
相关推荐
烟漠河洛14 分钟前
俄罗斯电商3200亿卢布疯长:跨境支付与多平台订单系统架构解析
mysql·php
江湖有缘22 分钟前
Docker实战 | 使用Docker部署Donetick任务与家务管理应用
运维·docker·容器
实心儿儿31 分钟前
Linux —— 应用层协议HTTP
linux·网络·http
流星白龙35 分钟前
【Docker】4.NameSpace空间隔离实战
java·运维·docker
有续技术1 小时前
哈斯 (Haas) 机床 IP、端口号配置内容总结
运维·服务器
小张同学a.2 小时前
LAMP架构2
linux·运维·网络·架构·负载均衡
千河殇 多想和她2 小时前
如何在Reaonix中使用CodeGraph以及CodeGraph效果实测经验分享
linux·运维·ubuntu
VortMall2 小时前
出海引流运维双升级|VortMall微服务商城系统v1.3.12 升级更新
运维·微服务·facebook
心念枕惊2 小时前
新写了个直播录制工具,可录制抖音快手斗鱼直播
运维·服务器·数据库
躺不平的理查德2 小时前
CMAKE备忘录
linux·运维·服务器