
在 Linux 中,終端機與 Shell 相關聯。終端將輸入傳送到 Shell(例如:pwd
),而 Shell 將輸出傳送回終端(例如:/home/paul
)。
下圖展示了 Terminal 和 Shell 之間的關係(假設我使用的 Terminal 是gnome-terminal
,Shell 是bash
):
現在我想知道的是終端機和Shell使用什麼機制來交換資料。這就是我認為發生的情況:
- 執行時
gnome-terminal
,會在目錄中建立一個代表串列埠的檔案/dev/pts
(假設檔案名稱/dev/pts/0
)。 gnome-terminal
然後將執行與其關聯的 Shell(例如:bash
),並向其傳遞 pts 檔名(例如,可以透過命令列參數傳遞 pts 檔名)。- 現在 和 都
gnome-terminal
將從bash
開始讀取/dev/pts/0
。 - 當
gnome-terminal
要發送數據時bash
,它會寫入該數據/dev/pts/0
,並bash
從中讀取該數據/dev/pts/0
。 - 當
bash
要發送數據時gnome-terminal
,它會寫入該數據/dev/pts/0
,and
gnome-terminal
並從中讀取該數據/dev/pts/0
。
該圖顯示了我剛剛解釋的內容:
我的理解正確嗎?
筆記:當然,如果我們使用虛擬終端(即,當我們不使用 GUI 時),pts 文件可以是 tty 文件,但邏輯仍然是相同的。
答案1
你缺少了一個必要的部分。偽 tty 裝置不像套接字那樣對稱。有主端和從端。中的文件/dev/pts
代表從設備。
終端模擬器透過呼叫建立一個偽 tty openpty
(或對於您想要在新 tty 上運行新進程的常見情況加上一些額外的設定)forkpty
。openpty
在較低級別,這涉及打開/dev/ptmx
並執行一些魔法 ioctl。
呼叫終端仿真器的結果是得到一對檔案描述符,也可以得到slave對應的openpty
檔案名稱。/dev/pts
主進程沒有單獨的名稱,因為子進程不需要按名稱打開它。
主設備和從設備的行為有點像是套接字的兩端:您在一端寫入的內容將從另一端讀取。但因為這是一個 tty,所以所有 tty 模式都會應用於途中的資料。
例如,如果您是終端模擬器,並且收到按鍵操作A,則應該寫入'a'
主檔案描述符。這直接相當於透過串行線路從終端將該位元組發送到電腦。它將導致'a'
從機讀取(透過任何正在讀取它的程式 - 例如 shell)。
D如果在按鍵按下時收到Ctrl按鍵按下,則應將一個4
位元組 ( 'D' ^ 0x40
) 寫入主文件描述符。 (因為這是真正的終端在線路上發送的內容。)接下來發生的情況取決於 tty 模式。在原始模式下,讀取從屬 tty 的程式將看到一個4
位元組。在cooked模式下,tty將啟動「EOF特殊鍵按下」行為。
在相反的方向上,也有一些處理。當某些程式寫入'\n'
從屬 tty 時,"\r\n"
由於onlcr
後處理,您可能會在主文件描述符上收到。
歷史部分,無聊可以跳過
很久以前,從設備的名稱如下/dev/ttyp0
,每個設備都有一個相應的主設備,例如/dev/ptyp0
。它們不是動態創建的。終端模擬器可以探測所有這些,找到目前未使用的一個,然後開始使用它。管理所有權和權限是一個問題。xterm
setuid-root 只是為了可以 chown 奴隸。
新方案稱為“UNIX98 ptys”,透過神奇的 ioctl 處理設備創建和所有權,因此文件僅在/dev/pts
使用時出現,並且由運行創建它們的程式的用戶擁有。