bash或其他shell中是否存在libc pipe()的等价实现?
关于
pipe()的简易等价实现 首先明确:shell层面没有完全和libc的pipe()一一对应的直接等价工具——毕竟pipe()是直接返回文件描述符给程序代码调用的系统调用封装,而shell工具都是面向进程间数据流编排的。不过有几种方式可以模拟出类似“拿到管道两端句柄”的效果,适合在shell脚本里实现接近pipe()的能力:
1. 利用/dev/fd和进程替换绑定文件描述符
shell里可以手动创建匿名管道并将两端绑定到指定文件描述符,比如bash下的写法:
# 将匿名管道的读写端绑定到文件描述符3 exec 3<> <(:) # 直接用fd3进行读写操作 echo "测试数据" >&3 cat <&3 # 使用完毕后关闭文件描述符 exec 3>&-
这里的<(:)是进程替换的变体,本质上会创建一个匿名管道,exec 3<>语法则把管道的读写端同时绑定到fd3。这种方式能拿到可直接操作的文件描述符,和pipe()返回fd的逻辑最为贴近。
2. 临时命名管道模拟匿名管道效果
结合mkfifo和文件描述符复用,可以实现和pipe()几乎一致的匿名管道效果:
# 创建临时命名管道路径 tmp_pipe=$(mktemp -u) mkfifo "$tmp_pipe" # 将管道读写端分别绑定到fd3和fd4 exec 3< "$tmp_pipe" 4> "$tmp_pipe" # 立即删除管道文件(因已打开句柄,管道仍可正常使用) rm "$tmp_pipe" # 通过fd操作管道 echo "hello pipe" >&4 read line <&3 echo "$line" # 关闭文件描述符 exec 3>&- 4>&-
这种方式用临时命名管道模拟了pipe()的匿名特性,同时保留了可直接操作的文件描述符。
3. 使用coproc(协同进程)获取管道句柄
bash的coproc命令会自动创建后台协同进程,并建立管道连接主进程与协同进程,你可以通过内置的COPROC变量拿到管道两端的文件描述符:
# 创建一个执行cat命令的协同进程 coproc cat # COPROC[0]是管道读端,COPROC[1]是管道写端 echo "测试协同进程管道" >&${COPROC[1]} cat <&${COPROC[0]} # 关闭管道句柄 exec ${COPROC[0]}>&- ${COPROC[1]}>&-
这种方式是shell帮你封装了pipe()+fork的逻辑,直接提供了可交互的管道fd,适合需要和后台进程双向通信的场景。
需要注意的是,这些shell层面的实现本质上都是基于系统调用pipe()封装的,只是给你提供了在脚本中操作管道fd的途径,而非替代pipe()本身。如果是在C/C++代码中,直接调用libc的pipe()仍是最直接的方式。
内容的提问来源于stack exchange,提问作者Philip Adler
相关产品推荐
相关产品推荐

