进程替换的实现以​​及进程替换中的并发

进程替换的实现以​​及进程替换中的并发

Bash 手册说

/dev/fd支持命名管道 (fifo) 或命名打开文件的方法的系统支持进程替换。

  1. 这是否意味着进程替换是通过命名管道或下面的文件来实现的/dev/fd
  2. Linux中是如何实现进程替换的?

    下面的示例是否意味着 Linux 中的进程替换是通过 下的文件/dev/fd而不是命名管道来实现的?

    $ echo <(cat)
    /dev/fd/63
    
  3. 在 中command1 <(command2),两个命令是同时运行,还是一个命令在另一个命令运行完成后才开始?

    如果进程替换是通过命名管道实现的,是否意味着进程替换示例中的两个命令同时运行?我的猜测是因为管道和命名管道用于并发运行的进程之间的通信,并且管道中的命令同时运行。

    我在尝试理解回复中的第 2 部分时遇到了这个问题 https://unix.stackexchange.com/a/286556/674

谢谢。

答案1

  1. strace的输出来看strace -v -f -s150 -o log bash -c 'echo <(cat)',在我的系统上,/dev/fd 被实现为管道。它创建具有 3、4 个 fd 的管道,然后复制 3 到 63。
  2. /dev/fd只是 的符号链接/proc/self/fd。我的系统缺少/dev/fd符号链接,输出只是/proc/self/fd/63. Bash 仅使用管道进行操作。在 bash 源代码中,它似乎可能像其他 bash'ism 一样被模拟,/dev/tcp但我不确定。不过我没有看到这些busybox ash
  3. 如果我echo用内置命令tty替换strace整个 bash,我确实看到它tty首先运行,然后cat使用预加载的管道 fd 执行。

答案2

1.、2.:是的,进程替换是通过命名管道来实现的(开源=你可以阅读源代码)

3.

如果进程替换是通过命名管道实现的,是否意味着进程替换示例中的两个命令同时运行?

是的,这确实意味着它们同时运行。

答案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 结束才能关闭读取,然后它会休眠并结束。

简而言之:它们同时运行。

相关内容