Linux间进程通信
进程间通信
进程间通信(简称IPC)是指多个进程之间传输数据或共享信息的机制。
通信目的
数据交换,共享资源,进程同步,消息传递。
实现原理
通信进程能够访问相同的内存区域。
进程间通信的方法
分为四大类:管道,System VIPC,POSIX IPC,套接字。
以下是对表格内容的提取整理,按照 方法分类 梳理各类进程间通信(IPC)的关键信息:
1. 管道(Pipe)
| 通信名称 | 描述 | 特点 |
|---|---|---|
| 无名管道 | 亲缘关系进程间通信 | 仅支持父子/兄弟进程 |
| 命名管道 | 任意进程间通信 | 需通过路径名标识管道 |
2. System V IPC
| 通信名称 | 实现方式 | 核心功能 |
|---|---|---|
| 消息队列 | IPC 命名空间 | 基于消息传递数据 |
| 信号量 | IPC 命名空间 | 实现进程间同步(如互斥锁) |
| 共享内存 | IPC 命名空间 + 内存映射 | 高效共享内存传递数据 |
3. POSIX IPC
| 通信名称 | 实现方式 | 核心功能 |
|---|---|---|
| 消息队列 | 文件系统(文件标识) | 基于消息传递数据 |
| 信号量 | 文件系统(文件标识) | 实现进程间同步 |
| 共享内存 | 文件 + 内存映射 | 高效共享内存传递数据 |
4. 套接字(Socket)
| 通信名称 | 描述 | 适用场景 |
|---|---|---|
| socket | 网络编程专题介绍 | 支持跨主机/跨网络通信 |
无名管道
介绍
无名管道用在具有亲缘关系的进程之间的单向通信。
特点
- 半双工
- 字节流通信,数据格式由用户自定义
- 多用于父子进程间通信
实现原理
父进程调用pipe函数创建两个文件,读管道文件和写管道文件。这两个文件的文件节点为pipe inode。
父子进程都能看到操纵管道,管道可以看作是缓冲区。

半双工原理
由于父进程和子进程都在写文件时,都写入了管道,读取时也都是在读取管道,没有办法区分。
全双工通信
使用两个通道
为什么只能亲缘关系
因为文件表不相同
编程实现
fork()
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
创建无名管道
int pipe(int pipefd[2]);
int pipe2(int pipeefd[2],int flags);
pipefd[0]:读文件描述符
pipefd[1]:写文件描述符
-
flags
O_NONBLOCK:设置非阻塞模式,读取和写入管道不会阻塞进程。O_CLOEXEC:设置在execve系统调用执行时关闭管道
-
返回值
- 成功返回0
- 失败返回-1,并设置errno
关闭、读写、初始化
int close(int fd);//关闭
ssize_t read(int fd, void *buf, size_t count);//读写
ssize_t write(int fd, const void *buf, size_t count);
//初始化
int fd[2] = {0};
//fd[0]:管道的读端(文件描述符,指向内核管道的读缓冲区)。
//fd[1]:管道的写端(文件描述符,指向内核管道的写缓冲区)。
完整流程演示
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#define TEST_STRING "Hello, Pipe!"
int fd[2] = {0}; //初始化
void test() {
pid_t pid = fork(); //创建子进程
if (pid == 0) {
close(fd[1]); // 子进程关闭写端
char rbuf[100];
while (1) {
memset(rbuf, 0, sizeof(rbuf));
int n = read(fd[0], rbuf, sizeof(rbuf)); //从管道读端 fd[0] 读取数据,
if (n == 0) { // 写端关闭,退出循环
printf("Child: Pipe EOF, exit.\n");
break;
}
printf("Child: Read %d bytes: %s\n", n, rbuf);
}
close(fd[0]); //子进程关闭读端(退出循环后执行)
_exit(0); // 子进程直接退出(避免执行父进程逻辑)
} else if (pid > 0) {
close(fd[0]); // 父进程关闭读端
}
}
int main(int argc, char *argv[]){
if (pipe(fd) == -1) { // 检查 pipe 创建失败
perror("pipe");
return 1;
}
test();
// 父进程写 5 次后退出
for (int i = 0; i < 5; i++) {
write(fd[1], TEST_STRING, strlen(TEST_STRING));
sleep(1);
}
close(fd[1]); // 父进程关闭写端(子进程会收到 EOF)
printf("Parent: Close write end, exit.\n");
return 0;
}
命名管道
介绍
FIFO文件(也称为命名管道)是一种特殊类型的文件,在Linux中用于进程间通信。FIFO文件允许不相关的进程通过读取和写入相同的文件来通信。
特点
- FIFO文件位于文件系统中,可以像其他文件一样进行访问和管理。
- FIFO文件可以通过名称进行识别和引用,而不仅仅依赖于文件描述符。
- FIFO文件可以在不同的进程之间进行双向通信,允许同时进行读取和写入操作。
实现原理
进程通过mkinfo函数创建一个FIFO文件,FIFO文件对应一个fifo inode,fifo inode和pipe inode底层实现相同。
命名管道通过mkinfo创建完后,进程调用open打开FIFO文件,由于每个文件都对应唯一的inode节点,所以多个进程都是打开相同的inode节点,成功打开FIFO文件后,进程能正常读写管道完成进程间通信。

编程实现
创建命名管道
int mkfifo(const char *pathname,mode_t mode);
参数
pathname:命名管道的路径
mode:创建的权限
返回值
成功返回0,失败返回-1,并设置errno
管道操作
使用IO open,write,read,close实现打开,写,读操作。
System V消息队列
简介
允许多个进程同时向消息队列中写入和读取消息。
通过消息优先级机制,可以优先处理重要的消息。
实现原理
具有相同IPC命名空间的进程能够访问IPC命名空间相同的内存空间。

ftok函数:用于生成Svstem V唯一键值。
msgget:通过key查找IPC对象。

浙公网安备 33010602011771号