在子 shell 中执行与使用 & 与 coproc 命令之间有什么区别?

在子 shell 中执行与使用 & 与 coproc 命令之间有什么区别?

我最近在阅读有关 linux 中的子 shell 的内容。使用的示例是 sleep 10。

(sleep 10)  -  subshell
sleep 10&   - background process
coproc sleep 10  

据记载,第一个命令在子 shell 中执行。第二种是不涉及子shell的后台进程。第三个是两者的结合。我已经使用测试过 ps -ef,所有这些命令都显示了子 shell 的创建。使用 & 和 subshel​​l 的后台进程有什么区别吗? coproc 似乎也在做同样的事情。我完全困惑了。任何有关该主题的说明将不胜感激。

答案1

在您的 shell 中,sleep不是 shell 的内置命令,因此在任何情况下都必须在单独的进程中执行(这在内置命令中ksh93mkshsleep内置命令中会有所不同)。

(sleep 10)实现了一个子shell环境。这个想法是,对 shell 环境(别名、变量、函数、umask、工作目录、重定向...)进行的任何修改只会影响它,并在返回(...)时丢失。(...)

在大多数 shell 中,这是通过分叉子进程来实现的。并非所有 shell 都这样做。ksh93相反,将以前的环境设置保存在堆栈上并在退出时恢复它们,并且在这种情况下不会分叉。

在许多 shell 中,作为一种优化,如果子 shell 中的最后一个命令是外部命令(如sleep您的情况),并且没有trap设置,则 shell 不会分叉进程来运行它,而是直接在子 shell 中运行它过程,因为无论如何之后都不需要该过程。

对于 shell bash,只有当该命令是子 shell 中的唯一命令时才会发生这种情况(这也是您的情况)。

sleep 10&并且coproc sleep 10还启动一个子 shell 环境,但在这些情况下,它们必须使用子进程来完成,因为您有两个并行执行的线程。两者之间的不同之处在于,在这种coproc情况下,子 shell 的 stdin 和 stdout 连接到两个管道以与父 shell 交互。

与本(...)例类似,如果子 shell 仅由一个命令组成,则该命令将直接在 shell 进程中执行。

为了更好地看到差异,您可能需要运行启动多个命令的子 shell,例如:

{ ps; echo done; } # no subshell
(ps; echo done)
{ ps; echo done; } &
coproc { ps; echo done; }

相关内容