歷史部分,無聊可以跳過

歷史部分,無聊可以跳過

在 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/0and gnome-terminal並從中讀取該數據/dev/pts/0

該圖顯示了我剛剛解釋的內容:

在此輸入影像描述

我的理解正確嗎?


筆記:當然,如果我們使用虛擬終端(即,當我們不使用 GUI 時),pts 文件可以是 tty 文件,但邏輯仍然是相同的。

答案1

你缺少了一個必要的部分。偽 tty 裝置不像套接字那樣對稱。有主端和從端。中的文件/dev/pts代表從設備。

終端模擬器透過呼叫建立一個偽 tty openpty(或對於您想要在新 tty 上運行新進程的常見情況加上一些額外的設定)forkptyopenpty在較低級別,這涉及打開/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。它們不是動態創建的。終端模擬器可以探測所有這些,找到目前未使用的一個,然後開始使用它。管理所有權和權限是一個問題。xtermsetuid-root 只是為了可以 chown 奴隸。

新方案稱為“UNIX98 ptys”,透過神奇的 ioctl 處理設備創建和所有權,因此文件僅在/dev/pts使用時出現,並且由運行創建它們的程式的用戶擁有。

相關內容