当前位置: 首页 > news >正文

Android随笔-pipe是什么?

pipe 是 Linux 内核提供的进程间通信(IPC)机制,本质上是一个内核管理的环形缓冲区(ring buffer),让两个进程可以通过文件描述符(FD)单向传输字节流。

一、pipe 是什么?

特性说明
本质内核中的环形缓冲区,存在于 RAM 中
方向单向(半双工):数据只能从一个方向流动
顺序FIFO(先进先出)
生命周期随进程结束而销毁,不持久化到磁盘
创建pipe()系统调用创建 2 个 FD

二、核心 API

#include<unistd.h>intpipe(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 页 = 64KB)structpage*tmp_page;structfasync_struct*fasync_readers;structfasync_struct*fasync_writers;structinode*inode;structuser_struct*user;};

关键点:

  • 内核分配一个页(page)数组作为缓冲区
  • 默认大小:16 页 = 64KB(PIPE_BUF)
  • 写指针和读指针维护 FIFO 顺序
  • 缓冲区满时,write() 阻塞(默认)或返回 EAGAIN(非阻塞)

五、阻塞 vs 非阻塞行为

场景阻塞模式(默认)非阻塞模式(O_NONBLOCK
read()时缓冲区为空阻塞,直到有数据返回-1errno = EAGAIN
write()时缓冲区满阻塞,直到有空间返回-1errno = EAGAIN
write() < PIPE_BUF原子写入(全有或全无)原子写入
write() > PIPE_BUF可能拆分写入可能拆分写入

六、pipe 在 Android Looper 中的应用(Legacy)

旧版 Android(Android 5.0 之前)用 pipe 实现 Looper 的线程唤醒:

// system/core/libutils/Looper.cpp (Legacy)Looper::Looper(boolallowNonCallbacks){// 创建 pipeintwakeFds[2];pipe(wakeFds);// or pipe2(wakeFds, O_CLOEXEC)mWakeReadPipeFd=wakeFds[0];// 读端mWakeWritePipeFd=wakeFds[1];// 写端// 将读端注册到 epollstructepoll_eventeventItem;eventItem.events=EPOLLIN;eventItem.data.fd=mWakeReadPipeFd;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?

对比项pipeeventfd
FD 数量2(读+写)1
内核缓冲区2 个 ring buffer1 个 64 位计数器
原子性不保证保证 64 位原子操作
系统调用开销pipe()+ 2 次fcntl()eventfd()一次
适用场景数据传输简单通知
Android 使用Legacy(pre-5.0)Modern(5.0+)

eventfd 更适合"通知"场景,因为它就是设计来做轻量级事件通知的。

八、常见使用场景

场景说明
Shell 管道`lsgrep txtls的 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。

http://www.jsqmd.com/news/1137781/

相关文章:

  • 如何彻底告别系统激活烦恼:KMS_VL_ALL_AIO智能激活脚本完全指南
  • 使用Wireshark深度解析PTP协议,精准定位工业网络时间同步故障
  • 微信小程序渲染层网络层错误排查:从 WXSS 图片到视频组件的 3 类常见根因与修复
  • Unity GraphView 与 IMGUI 节点编辑器对比:3 大维度性能与开发效率实测
  • Debian安装Docker最佳实践:官方源、overlay2与docker组权限
  • Tampermonkey 脚本开发实战:10个JS函数实现中国大学MOOC题目一键复制
  • 终极Monaspace编程字体完整指南:如何提升代码可读性与开发效率
  • Solarflare OpenOnload 201811 安装实战:Ubuntu 22.04 系统下 3 步完成驱动与固件升级
  • 多Agent协作:构建分布式智能系统
  • LinuxCNC终极指南:如何从零开始搭建开源数控系统
  • Shell脚本精读 · S09-02 | 管道与管道退出码:`pipefail` 再探
  • Unity 移动平台帧率优化:WebGL 与 Android 120Hz 屏幕的 4 个适配要点
  • UE5 Control Rig 受击响应实战:2个控制器+Fullbody IK 实现8方向动态反馈
  • STM32与EM3080-W构建工业级条形码识别系统
  • 偏微分方程数值解避坑指南:有限差分法3大稳定性条件与误差分析
  • Linux 进程管理进阶:kill -9 与 -15 的3种场景选择与僵尸进程清理
  • Excel电子签名的法律效力与技术实现全解析
  • Android随笔-ThreadLocal
  • Cron Jobs在数据工程中的生产级实践:从定时任务到可靠数据管道
  • 从零部署Gemma大模型:本地化实践与性能优化指南
  • STM32与KMR221构建高精度电压管理系统
  • 告别CPC客户端安装失败:IE与CA证书环境配置终极指南
  • TC78H660FTG与PIC18F46K20构建高效电机驱动系统
  • TPAFE0808与STM32L031C6的多通道信号采集系统设计
  • ENVI 5.3 空间滤波实战:3x3与9x9核下4种算子锐化效果对比
  • BurpSuite插件开发实战:从功能实现到生产级优化的进阶指南
  • GPT-4o 多模态应用:5步构建自然场景对话助手,情感识别准确率超85%
  • 每天10分钟学会OceanBase系列(Day 11):备份与恢复,给数据上一道“保险”
  • RHCE实验环境搭建:1台主机同时配置HTTPS网站与DHCP服务器的3个关键点
  • ASM330LHH与STM32L4S5ZI的硬件协同设计与运动跟踪算法