
有這兩個名字:a子外殼和一個子殼。
是的,子進程將透過以下任一方式啟動:
sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat
都是等價的並且具有相同的名稱嗎?所有人都具有相同的屬性嗎?
POSIX有這個定義:
shell執行環境包括......
但上面連結的最後一段是這樣的:
子 shell 環境應建立為 shell 環境的副本,但未被忽略的訊號陷阱應設定為預設操作。
特別是:
命令替換、用括號分組的命令以及非同步列表應在子 shell 環境中執行。此外,多命令管道中的每個命令都位於子shell環境中; ....
不sh -c 'echo "Hello"'
包含在那裡,那也應該稱為子shell嗎?
答案1
一個子shell重複項現有的外殼。它具有相同的變數、相同的函數、相同的選項等。fork
系統調用²;子程序繼續執行預期的操作,而父程序則等待(例如,$(…)
)或繼續其生命(例如,… &
)或以其他方式執行預期的操作(例如,… | …
)。
sh -c …
不建立子shell。它啟動另一個程式。程式恰好是一個 shell,但這只是一個巧合。該程式甚至可能是不同的 shell(例如,如果您sh -c …
從 bash 運行,並且sh
是 dash),即一個完全不同的程序,只是其行為恰好有顯著的相似之處。在幕後,啟動外部命令(sh
或任何其他命令)會調用fork
系統調用,然後execve
系統調用代替子進程中的 shell 程式由另一個程式執行(此處sh
)。
¹包括$$
,但不包括一些特定於 shell 的變量,例如 bash 和 mksh 的BASHPID
。
²至少,這是傳統且通常的實作方式。如果 shell 能夠模仿行為,那麼它們就可以最佳化分叉。看「子shell」和「子進程」之間的確切差異是什麼?
答案2
子 shell 環境不需要存在於單獨的進程中,它只需要複製目前的執行環境。這ksh93
是透過virtual sub-shell
不調用fork()
.這使得 ksh93 在像 一樣的古老平台上非常快Win-DOS
,而Win-DOS
分叉時卻非常慢。
sh -c cmd
另一方面,使用預設 shell 建立一個新進程,該進程不需要與目前的互動式 shell 相同。
即使sh
當前 shell 相同,也不會複製執行環境,因此不會創建sub-shell
.