Tcsh
為什麼 tcsh 始終有多個 fd 指向 /dev/tty
這是在 Ubuntu 16.04 上,帶有 bash 4.3.42 和 tcsh 6.19
如果打開 X 未使用的虛擬控制台並執行 bash,我會看到標準輸入、標準輸出、標準錯誤和 tty 的專用文件描述符(顯然)。
$ cd /dev/fd $ ls 0 1 2 255 $ ls -al . ... . ... .. ... 0 -> /dev/tty3 ... 1 -> /dev/tty3 ... 2 -> /dev/tty3 ... 255 -> /dev/tty3
如果我使用 tcsh,我會看到五個指向 tty 的非 std{in、out、err} 文件描述符,並且 std{in、out、err} 都映射到
/dev/null
.% cd /dev/fd % ls -al ... . ... .. ... 0 -> /dev/null ... 1 -> /dev/null ... 15 -> /dev/tty3 ... 16 -> /dev/tty3 ... 17 -> /dev/tty3 ... 18 -> /dev/tty3 ... 19 -> /dev/tty3 ... 2 -> /dev/null
為什麼
tcsh
需要這麼多文件描述符都指向 tty,將 0,1 和 2 映射到 tty 有什麼好處/dev/null
?這難道不只是意味著在tcsh
分叉程序時需要稍微增加一點簿記,以便它們寫入/從控制台讀取嗎?
tcsh
的組織方式與bash
(不足為奇)不同。兩者都很古老,並且對於細心的讀者來說充滿了有趣的怪癖。這種差異是由於
tcsh
管理文件描述符的方式造成的。與 不同bash
的是,它不為腳本編寫者提供操作編號文件描述符的方法。開發人員發現通過將標準流移動到“已保存”區域(實際腳本不使用)來組織其文件描述符很方便,並且在執行命令時,它將這些命令複製到命令(即子程序),並在執行時關閉它們命令完成。在原始碼中,
sh.h
有這個塊解釋了這些文件描述符的使用:/* * The shell moves std in/out/diag and the old std input away from units * 0, 1, and 2 so that it is easy to set up these standards for invoked * commands. */ #define FSAFE 5 /* We keep the first 5 descriptors untouched */ #define FSHTTY 15 /* /dev/tty when manip pgrps */ #define FSHIN 16 /* Preferred desc for shell input */ #define FSHOUT 17 /* ... shell output */ #define FSHDIAG 18 /* ... shell diagnostics */ #define FOLDSTD 19 /* ... old std input */
對於這兩個 shell,在(至少對於 Linux)中,有多個指向同一個“真實”設備的連結
/dev/fd
,因為這是偽終端驅動程序的組織方式。
tcsh
順便說一句,如果你從另一個 shell執行,你會得到不同的結果。但是,如果您的預設 shell 是tcsh
,您可能會看到問題中描述的那些文件描述符。