【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 命名空间提升系统隔离性与安全性。
相关推荐
疯狂吧小飞牛5 小时前
GPG基础指令
linux·服务器·网络
C++ 老炮儿的技术栈6 小时前
volatile使用场景
linux·服务器·c语言·开发语言·c++
todoitbo7 小时前
用虚拟局域网打通 Win/Mac/Linux 三端:跨设备协作的实用方案
linux·运维·macos
源远流长jerry7 小时前
RDMA 基本操作类型详解:从双端通信到单端直访
linux·网络·tcp/ip·ip
Sylvia-girl8 小时前
Linux下的基本指令1
linux·运维·服务器
wyt5314298 小时前
Redis的安装教程(Windows+Linux)【超详细】
linux·数据库·redis
17(无规则自律)9 小时前
【Linux驱动实战】:字符设备之ioctl与mutex全解析
linux·c语言·驱动开发·嵌入式硬件
CDN3609 小时前
360CDN SDK 游戏盾:轻量化接入 + 强防护实测
运维·游戏·网络安全
Stewie121389 小时前
Docker 面试题
运维·docker·容器
星纬智联技术10 小时前
GEO E2E 自动化验证测试文章
运维·自动化·geo