2014-12-27 174 views
2

我在阅读The TTY demystified。在“乔布斯和会话”一节中有使用的xterm用户的例子:bash子shell是否会产生一个新的`bash`进程?

$ cat 
hello 
hello 
^Z 
[1]+ Stopped     cat 
$ ls | sort 

而且还有一个表,列出涉及的过程:xtermbash(该xterm的孩子),以及最后三个进程(cat,lssort)都具有相同的PPID(父进程ID) - 它们都是相同bash进程的子进程。

现在,我知道在bash中的管道在subbells中执行。我一直认为这个子shell的意思是每个子shell都有一个额外的bash进程。我的问题是:不应该有另外两个bash进程,第一个子进程bash,然后ls将是第一个子进程bash,并且sort将是第二个子进程bash?文章中的表格是简化的,还是我对subshel​​l的理解是错误的?

+1

Bash的行为是可配置的;用默认设置(尤其是'管道......在子壳中执行'不准确),你的普遍性并不完全准确。参见['PIPESTATUS'](http://www.gnu.org/software/bash/manual/bash.html#Bash-Variables)和['shopt -s lastpipe'](http://www.gnu.org /software/bash/manual/bash.html#The-Shopt-Builtin)和['set -o pipefail'](http://www.gnu.org/software/bash/manual/bash.html#The-Set -Builtin)。 – 2014-12-27 21:42:21

回答

2

程序在子进程中执行,但这些不是子壳。外壳会分叉一个孩子,根据需要重定向标准输入/输出/错误,然后立即调用execv()执行该程序。

在很短的时间内,子进程仍在运行bash,但我们不认为这是一个子shell,因为它没有执行任何shell命令处理 - 这些都是在原始shell中完成的,并且子级只是启动外部程序(就像通过明确的exec来执行命令ls一样)。

对于管道的情况,如果任何命令是shell内置函数,它们将在子shell中运行。所以如果你这样做:

ls | read var 

它会创建两个子进程。一个孩子将运行ls,另一个孩子将执行read var的子shell。

+0

在我的理解中,你所描述的对于像上面的'cat'命令这样的过程是正确的。但我的问题特别是关于管道。管道总是运行在一个子shell中,对吧? – fonini 2014-12-27 20:50:39

+0

我已经更新了解释在管道中运行的子壳体的答案。 – Barmar 2014-12-27 20:53:26

2

无论是直接还是通过管道调用可执行文件都不会产生子shell。只有在子shell中明确调用它(通过(...),$(...)等)才可以。

+0

我认为每条管道都会强制子壳产生。这是错的吗? – fonini 2014-12-27 20:52:37

+0

如果管道后面是一个shell构造,例如管道,管道只强制子壳产生。 'while'或函数。 – 2014-12-27 20:55:30