Zsh
在 zsh 中,cat <(cat) 與 cat | 之間的區別貓對貓=(貓)?
我期望
cat <(cat)
並cat | cat
做同樣的事情:將行從標準輸入複製到標準輸出。我的理解是,兩者都會cat
在子shell 中執行 a ,將 subshellcat
的 stdout 重定向到臨時命名管道,然後cat
在目前 shell 中執行另一個,並將其 stdin 重定向到管道。相反,
cat <(cat)
讓我在終端輸入,但沒有輸入行被複製並且^D
無法發出信號EOF
;cat | cat
雖然按預期工作。作為進一步的實驗,我檢查了是否
cat =(cat)
有與 類似的困難cat <(cat)
,但它按我的預期工作:所有標準輸入到 a^D
都被一次性複製到標準輸出。誰能幫我理解 zsh 在幕後做了什麼?
a | b
只需STDOUT
使用.a
_ _ _ 兩個命令並行執行。STDIN``b
dup/dup2
a =(b)``a
用臨時文件名替換參數 to 。b
將在之前執行,a
因為需要創建臨時文件才能將其傳遞給a
a <(b)``a
用命名管道替換參數。a
並b
並行執行。現在這有點複雜:•
b
在後台,無法從終端讀取。您可以自己測試它,方法是使用strace -p $PID
附加到您的第二個 cat 程序以查看該程序。•
a
同時嘗試從命名管道讀取,但無法讀取任何內容,因為b
無法讀取。• 這意味著您基本上遇到了死鎖,
a
嘗試讀取b
但b
無法讀取STDIN
且無法寫入a
來自man bash的有關後台程序和終端的更多資訊:
為了便於實現作業控制的使用者界面,作業系統維護了目前終端程序組 ID的概念。此程序組的成員(程序組 ID 等於目前終端程序組 ID 的程序)接收鍵盤生成的信號,例如 SIGINT。據說這些程序處於前台。背景程序是那些程序組 ID 與終端不同的程序;這樣的過程不受鍵盤生成的信號的影響。只允許前台程序讀取,或者,如果使用者使用 stty tostop 指定,則寫入終端。嘗試從終端讀取(當 stty tostop 生效時寫入)終端的後台程序由核心的終端驅動程序發送一個**SIGTTIN (SIGTTOU)**信號,除非被擷取,否則它將掛起該程序。