2014-12-27 175 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