命名管道(fifo)是带路径名的内核缓冲区,专为无亲缘关系进程通信设计;数据仅驻内存、不落盘,ls显示大小恒为0;默认读写均阻塞,需双方就绪才通行,天然适配循环脚本与后台服务的协同。

命名管道(FIFO)特别适合在循环脚本和后台服务之间做轻量、可靠的数据传递——它不依赖进程亲缘关系,也不需要网络栈或复杂同步逻辑,只要双方约定好路径,就能像读写文件一样通信。
命名管道是“带门牌号的内核缓冲区”,不是普通文件。它在文件系统里可见(如 /tmp/myfifo),但数据只存于内存,大小始终为 0;写入后必须有读端及时取走,否则写操作会阻塞(默认行为);读端打开时若无写端,也会阻塞(除非加 O_NONBLOCK)。这个特性恰恰让循环与后台任务能自然协同:一个等数据,一个发数据,不用轮询、不耗 CPU。
如何创建并初始化命名管道
必须先创建,再使用。创建只需一次,即使后台任务重启也无需重做:
mkfifo /tmp/loop2task.fifo chmod 600 /tmp/loop2task.fifo # 限制权限,避免其他用户误读写
- 创建后可用
ls -l验证:显示类型为p(如prw-------),大小为 0。 - 不要尝试用
touch或重定向>初始化它——这会触发阻塞或报错。
循环脚本作为数据生产者(发送端)
典型场景:每 5 秒采集一次指标,推给后台处理:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
#!/bin/bash
while true; do
echo "$(date +%s):$(uptime | awk '{print $10}')" > /tmp/loop2task.fifo
sleep 5
done
- 注意:
>是覆盖式重定向,对 FIFO 有效,等价于echo ... | tee /tmp/loop2task.fifo。 - 如果后台任务还没启动,该命令会卡住,直到有进程以读方式打开 FIFO —— 这正是你想要的“等待就绪”行为。
后台任务作为消费者(接收端)
用 while read 持续监听,适合长期运行的服务:
#!/bin/bash # 后台任务:持续读取并处理 while IFS= read -r line; do timestamp=$(echo "$line" | cut -d: -f1) load=$(echo "$line" | cut -d: -f2) logger "TASK: got load $load at $timestamp" # 这里可调用 Python 脚本、写数据库、发告警等 done
- 必须用
打开读端,且不能放在子 shell(如 <code>(...) )里,否则读完一次就退出。 - 若希望启动时不阻塞(比如后台任务先跑,循环后起),可在
open()时加O_NONBLOCK,但 shell 本身不直接支持;更稳妥的做法是用exec 3 预打开,再配合 <code>read -u3。
避免常见卡死问题
-
两端都未打开时,任一端
open()会阻塞:这是默认语义,合理利用即可。若需非阻塞,C 程序中用open(..., O_RDONLY | O_NONBLOCK);shell 中可配合timeout或改用stdbuf+cat做兜底。 -
只开写端不关,读端
read()返回 EOF 后退出:确保写端进程正常退出时关闭 fd(shell 中命令结束即自动关闭)。 -
多个写端同时写,内容可能交错:FIFO 保证单次
write()小于 PIPE_BUF(通常 4096 字节)是原子的;超过则可能被拆分。建议每行一条记录,用换行符分隔。 -
管道文件残留:
rm /tmp/loop2task.fifo即可清除。它不占磁盘空间,删了就真没了。
可选增强:支持重启与断连恢复
如果后台任务崩溃重启,循环端还在持续写,而新读端打开时可能错过数据。此时可加一层简单容错:
- 循环端每次写前先检查 FIFO 是否可读(
if [[ -p /tmp/loop2task.fifo ]] && [[ -r /tmp/loop2task.fifo ]]; then ...) - 或改用
stdbuf -oL+cat组合,让写入更实时:while true; do echo "$(date):$(df -h / | tail -1)" | stdbuf -oL cat > /tmp/loop2task.fifo sleep 10 done
本质上,命名管道在这里扮演的是“同步信道”角色:它天然把生产节奏和消费节奏耦合起来,不需要额外信号、锁或状态判断。只要路径一致、权限到位、读写模式匹配,就能稳稳工作。










