1. 管道:进程间通信的基石
在操作系统的世界里,进程就像一个个孤岛,彼此隔离却又需要协作。管道(Pipe)就是连接这些孤岛的最古老也最可靠的桥梁之一。我第一次接触管道是在调试一个多进程日志系统时,当时需要将子进程的日志实时传递给父进程处理,管道完美解决了这个问题。
管道本质上是一个内核维护的环形缓冲区,它允许两个相关进程(通常是父子进程)以先进先出(FIFO)的方式进行单向数据流动。这种设计简单却高效,就像连接两个水桶的软管,数据像水流一样自然地从一端流向另一端。在Linux系统中,管道是IPC(进程间通信)机制中使用频率最高的方式之一,特别是在shell命令组合中随处可见它的身影。
关键特性:管道默认大小通常是65536字节(64KB),这个值定义在Linux内核的PIPE_BUF常量中。当写入数据量超过PIPE_BUF时,写操作可能被阻塞,直到有足够空间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 无名管道 vs 有名管道:两种实现方式
2.1 无名管道(匿名管道)
无名管道是最基础的形态,通过pipe()系统调用创建。我在实际项目中发现它有以下几个典型特征:
c复制int pipe(int pipefd[2]); // 经典创建方式
- 只能用于具有亲缘关系的进程间通信(如父子进程)
- 生命周期随进程结束而终止
- 单向通信,pipefd[0]用于读,pipefd[1]用于写
- 内核缓冲区大小有限(可通过fcntl设置)
一个典型的使用场景是shell中的命令管道符"|"。比如ls | grep .txt,shell会创建两个进程和一个管道,将ls的输出重定向到grep的输入。
2.2 有名管道(FIFO)
有名管道通过mkfifo创建,解决了无名管道的亲缘关系限制:
bash复制mkfifo mypipe # 命令行创建
或者用C代码:
c复制mkfifo("/tmp/mypipe", 0666);
我在一个跨进程日志收集系统中使用过有名管道,它的优势在于:
- 不相关进程可通过文件系统路径访问
- 持久化于文件系统(除非显式删除)
- 支持多读多写(需自行处理竞争条件)
实际经验:在Linux下,有名管道文件在磁盘上不占用实际空间,仅作为访问入口存在。删除管道文件会立即断开所
