pipe 是 Linux 内核提供的进程间通信IPC机制本质上是一个内核管理的环形缓冲区ring buffer让两个进程可以通过文件描述符FD单向传输字节流。一、pipe 是什么特性说明本质内核中的环形缓冲区存在于 RAM 中方向单向半双工数据只能从一个方向流动顺序FIFO先进先出生命周期随进程结束而销毁不持久化到磁盘创建pipe()系统调用创建 2 个 FD二、核心 API#includeunistd.hintpipe(intpipefd[2]);// pipefd[0] 读端read end// pipefd[1] 写端write end// 现代版本intpipe2(intpipefd[2],intflags);// flags: O_NONBLOCK非阻塞, O_CLOEXEC执行时关闭// 示例intfd[2];pipe(fd);// 或 pipe2(fd, O_NONBLOCK | O_CLOEXEC)write(fd[1],Hello,5);// 向写端写入read(fd[0],buf,100);// 从读端读取三、架构图四、内核实现环形缓冲区// Linux Kernel: fs/pipe.cstructpipe_inode_info{structmutexmutex;structpipe_buffer*bufs;// 环形缓冲区数组unsignedinthead;// 写指针unsignedinttail;// 读指针unsignedintring_size;// 缓冲区大小默认 16 页 64KBstructpage*tmp_page;structfasync_struct*fasync_readers;structfasync_struct*fasync_writers;structinode*inode;structuser_struct*user;};关键点内核分配一个页page数组作为缓冲区默认大小16 页 64KBPIPE_BUF写指针和读指针维护 FIFO 顺序缓冲区满时write() 阻塞默认或返回 EAGAIN非阻塞五、阻塞 vs 非阻塞行为场景阻塞模式默认非阻塞模式O_NONBLOCKread()时缓冲区为空阻塞直到有数据返回-1errno EAGAINwrite()时缓冲区满阻塞直到有空间返回-1errno EAGAINwrite() PIPE_BUF原子写入全有或全无原子写入write() PIPE_BUF可能拆分写入可能拆分写入六、pipe 在 Android Looper 中的应用Legacy旧版 AndroidAndroid 5.0 之前用 pipe 实现 Looper 的线程唤醒// system/core/libutils/Looper.cpp (Legacy)Looper::Looper(boolallowNonCallbacks){// 创建 pipeintwakeFds[2];pipe(wakeFds);// or pipe2(wakeFds, O_CLOEXEC)mWakeReadPipeFdwakeFds[0];// 读端mWakeWritePipeFdwakeFds[1];// 写端// 将读端注册到 epollstructepoll_eventeventItem;eventItem.eventsEPOLLIN;eventItem.data.fdmWakeReadPipeFd;epoll_ctl(mEpollFd,EPOLL_CTL_ADD,mWakeReadPipeFd,eventItem);}voidLooper::wake(){// 向写端写入 1 字节触发 epoll_wait 返回write(mWakeWritePipeFd,W,1);}voidLooper::awoken(){// 从读端读取清空 pipecharbuffer[16];read(mWakeReadPipeFd,buffer,sizeof(buffer));}七、为什么 Android 从 pipe 切换到 eventfd对比项pipeeventfdFD 数量2读写1内核缓冲区2 个 ring buffer1 个 64 位计数器原子性不保证保证 64 位原子操作系统调用开销pipe() 2 次fcntl()eventfd()一次适用场景数据传输简单通知Android 使用Legacypre-5.0Modern5.0eventfd 更适合通知场景因为它就是设计来做轻量级事件通知的。八、常见使用场景场景说明Shell 管道lsgrep txt—ls的 stdout 通过 pipe 连接到grep 的 stdin父子进程通信fork()后pipe()让父子进程交换数据Android LooperLegacy 唤醒机制已被 eventfd 替代自管道技巧信号处理中信号处理函数向 pipe 写主循环从 pipe 读避免信号处理中的异步问题九、总结pipe 是 Linux 内核提供的单向字节流 IPC 机制通过 pipe() 创建两个文件描述符fd[0] 读端、fd[1] 写端数据在内核环形缓冲区中按 FIFO 顺序流动。旧版 Android Looper 用 pipe 实现线程唤醒写端触发 epoll_wait 返回现代 Android 用更高效的 eventfd 替代了 pipe。