Tcsh

為什麼 tcsh 始終有多個 fd 指向 /dev/tty

  • July 31, 2016

這是在 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,您可能會看到問題中描述的那些文件描述符。

引用自:https://unix.stackexchange.com/questions/292146