Bash 手册说
/dev/fd
支持命名管道 (fifo) 或命名打开文件的方法的系统支持进程替换。
- 这是否意味着进程替换是通过命名管道或下面的文件来实现的
/dev/fd
? Linux中是如何实现进程替换的?
下面的示例是否意味着 Linux 中的进程替换是通过 下的文件
/dev/fd
而不是命名管道来实现的?$ echo <(cat) /dev/fd/63
在 中
command1 <(command2)
,两个命令是同时运行,还是一个命令在另一个命令运行完成后才开始?如果进程替换是通过命名管道实现的,是否意味着进程替换示例中的两个命令同时运行?我的猜测是因为管道和命名管道用于并发运行的进程之间的通信,并且管道中的命令同时运行。
我在尝试理解回复中的第 2 部分时遇到了这个问题 https://unix.stackexchange.com/a/286556/674。
谢谢。
答案1
- 从
strace
的输出来看strace -v -f -s150 -o log bash -c 'echo <(cat)'
,在我的系统上,/dev/fd 被实现为管道。它创建具有 3、4 个 fd 的管道,然后复制 3 到 63。 /dev/fd
只是 的符号链接/proc/self/fd
。我的系统缺少/dev/fd
符号链接,输出只是/proc/self/fd/63
. Bash 仅使用管道进行操作。在 bash 源代码中,它似乎可能像其他 bash'ism 一样被模拟,/dev/tcp
但我不确定。不过我没有看到这些busybox ash
。- 如果我
echo
用内置命令tty
替换strace
整个 bash,我确实看到它tty
首先运行,然后cat
使用预加载的管道 fd 执行。
答案2
答案3
对于第 3 点,如果我们定义:
$ d(){ printf '%7s %7s %s\n' "$BASHPID" "$1" $(date -u +'%H:%M:%S'); }
$ p1(){ d START; readarray -t a; printf '%s\n' "${a[@]}" ; sleep 2; d END; }
$ p2(){ d START; sleep 2; d END; }
然后,这个:
$ p1 < <(p2)
将打印:
8517 START 20:31:38
11764 START 20:31:38
11764 END 20:31:40
8517 END 20:31:42
这意味着两者一起开始,但 p1 必须等待 p2 结束才能关闭读取,然后它会休眠并结束。
简而言之:它们同时运行。