據我所知,/dev/pts
文件是為 ssh 或 telnet 會話創建的。
答案1
中沒有儲存任何內容/dev/pts
。該檔案系統純粹存在於記憶體中。
條目/dev/pts
是偽終端(簡稱pty)。 Unix 核心有一個通用概念終端。終端為應用程式提供了一種透過終端顯示輸出和接收輸入的方法。終端設備。一個進程可能有一個控制終端— 對於文字模式應用程序,這就是它與用戶互動的方式。
終端可以是硬體終端(“tty”,“teletype”的縮寫)或偽終端(“pty”)。硬體終端透過某些介面連接,例如序列埠 ( ttyS0
, …) 或 USB ( ttyUSB0
, …) 或透過 PC 螢幕和鍵盤 ( tty1
, …)。偽終端由終端仿真器提供,它是一個應用程式。一些類型的偽終端是:
- GUI 應用程式(例如 xterm、gnome-terminal、konsole 等)將鍵盤和滑鼠事件轉換為文字輸入並以某種字體以圖形方式顯示輸出。
- 多工器應用程式(例如 screen 和 tmux)中繼來自另一個終端的輸入和輸出,以將文字模式應用程式與實際終端解耦。
- 遠端 shell 應用程式(例如 sshd、telnetd、rlogind 等)在客戶端上的遠端終端和伺服器上的 pty 之間中繼輸入和輸出。
如果程式開啟終端進行寫入,則該程式的輸出將顯示在終端機上。多個程式同時輸出到終端是很常見的,儘管這有時會令人困惑,因為無法區分輸出的哪一部分來自哪個程式。嘗試寫入其控制終端的後台進程可能是由 SIGTTOU 訊號自動暫停。
如果程式打開終端機進行讀取,則使用者的輸入將傳遞到該程式。如果多個程式從同一終端讀取,則每個字元將獨立路由到其中一個程式;不建議這樣做。通常,在給定時間只有一個程式主動從終端讀取資料;當程式不在控制終端中時嘗試從控制終端讀取數據前景是由 SIGTTIN 訊號自動暫停。
要進行實驗,請tty
在終端機中運行以查看終端設備是什麼。假設它是/dev/pts/42
.在另一個終端的 shell 中,運行echo hello >/dev/pts/42
:該字串hello
將顯示在另一個終端上。現在運行cat /dev/pts/42
並在另一個終端機中輸入。若要終止該cat
命令(這將使另一個終端難以使用),請按Ctrl+ C。
寫入另一個終端有時對於顯示通知很有用;例如write
命令就是這樣做的。通常不會從另一個終端機讀取資料。
答案2
中的文件/dev/pts
是“pseudo-ttys”。它們在某種程度上類似於命名管道,但它們也模仿舊的串行連接終端,例如 VT-100。偽 tty 負責將位元組從鍵盤傳輸到程序,以及從程式傳輸到輸出設備,這聽起來很簡單。但這回答了您明確的問題:/dev/pts/0
例如,核心不儲存任何內容。只有連接到偽 tty 的程式的 stdout 的位元組流才會進入,並且 stdin 連接到同一偽 tty 的程式會讀取這些位元組。
偽 tty 也在這些位元組流中放置了一個間接層。核心可以檢查位元組中的特殊值,例如“Control-C”或“Control-D”或“Control-U”(這些都是可配置的,請參閱 參考資料man stty
)並發送SIGINT、在stdin 上設定文件結尾或擦除輸入上的一行。那裡還有一個緩衝功能,所以我的“不存儲任何內容”有點錯誤,但只有幾千位元組。
核心可以檢查輸出上的位元組值,並執行諸如將換行符(ASCII 換行符、LF 或"\n"
)轉換為兩個位元組、回車符和換行符(CRLF 或"\r\n"
)或序列終端硬體所需的任何字節之類的操作。偽終端的間接性允許獨立於硬體。
偽 tty 還允許所有「設定波特率」、「設定奇偶校驗」等ioctl()
系統調用,並且可能對它們不執行任何操作。這使得在 VT-100、ADM-3 和 Wyse 時代編寫的程式能夠繼續運作而不會出錯。軟體(偽 ttys 裝置驅動程式)的作用類似於硬體。
偽 tty 可以由sshd
和使用telnet
,但它們也可以在終端模擬器(如xterm
或rxvt
)和通常在 xterm 內運行的 shell 之間使用。
Linux 和許多 Unix 有偽 tty。計劃9則不然。偽 tty 有點像遺跡,是串行電纜連接硬體終端時代遺留下來的。
答案3
/dev/
是設備檔案的特殊目錄。這些是抽象的,它們不是磁碟上的真實檔案。該目錄在啟動時填充,並且可能會發生更改以反映現有的設備接口,這些接口由核心和用戶空間守護程序創建和銷毀udevd
。
如此表示的許多設備都是虛擬的。這包括 中的條目/dev/pts
,它們是控制台設備。這就是為什麼要為遠端會話建立一個會話;當您開啟本機 GUI 終端機時也會建立它們。
您可以將它們作為文件打開,儘管它沒有多大用處。若要取得/dev/pts
shell 連線的節點,請使用tty
:
> tty
/dev/pts/4
現在切換到其他控制台並嘗試:
> echo "duck!" > /dev/pts/4
聰明的。現在嘗試:
> cat /dev/pts/4
然後嘗試使用 /dev/pts/4 處的 shell。你會被困住,直到你退出cat
另一邊,但你在 pts/4 上輸入的大部分內容都會通過(例如嘗試“hello world”,我最終在hl
pts/4 和控制台ello word
上輸入cat
)。
我的猜測是,設備正在從 shell 獲取輸入,並透過系統輸出它,這就是內容最終出現在螢幕上的方式——shell 不處理硬件,而是系統。嘗試(如果你不知道它是什麼,strace bash
請看一下);man strace
當 bash 啟動時,你會收到一連串的通話。現在開始敲擊按鍵:
read(0, "h", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "h", 1h) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "e", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "e", 1e) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "y", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "y", 1y) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
對於輸入的每個字母,都會從標準輸入讀取並寫入標準輸出。但是 shell 的標準輸出連接到什麼?現在嘗試strace
在你的 GUI 終端機上——如果你不知道它的名字,你必須找出它的名字,例如在 KDE 上它是konsole
,我相信 GNOME 上有gnome-terminal
。其輸出strace
可能更加神秘——我的輸出有很多poll()
和recvfrom()
。我沒有看到任何寫入,但是如果您現在cat
從另一個終端中提取技巧,您會注意到當您鍵入時, cat 讀取的擊鍵導致 strace 輸出中根本沒有響應 - 終端是'沒有收到它們。因此,GUI 終端應用程式和 cat 競爭從 shell 輸出到的相同裝置進行讀取。