Terminal

每個偽終端 (PTY) 組件(軟體、主端、從端)的職責是什麼?

  • December 24, 2019

我試圖弄清楚tty 是如何工作的1(每個元素的工作流程和職責)。我已經閱讀了幾篇關於它的有趣文章,但仍有一些模糊的地方。

這是我目前所理解的:

  • 模擬終端/dev/ptmx對偽終端的主要部分進行不同的系統呼叫。
  • 偽終端的主機部分在 中分配一個文件/dev/pts/[0-N],對應於過時的串列埠,並將一個從偽終端“附加”到它。
  • 從偽終端保存會話ID、前台作業、螢幕大小等資訊。

以下是我的問題:

  1. 除了分配從屬部分之外,ptmx 還有其他用途嗎?它是否提供某種“智能”,或者模擬終端(例如 xterm)具有像終端一樣行為的所有智能?
  2. 為什麼 xterm必須與 master 部分互動,因為它只轉發 slave 部分的 stdout 和 stdin?為什麼不能 直接讀寫pts文件
  3. 會話 ID 是否始終附加到一個 pts 文件,反之亦然?我可以輸入一個 ps 命令並為同一個 /dev/pts/X 找到 2 個 sessionId嗎?
  4. pts商店還有哪些其他資訊?Xterm 是自己更新所有欄位,還是在ptm上面添加一些“智能”?

  1. 我的理解基於Linus Akesson 揭秘的 TTYAndries Brouwer 的 Linux Kernel文章,以及這些網站上的其他幾個問題

終端仿真器

主端取代了連接到終端的線路(一對 TX/RX 線)。

終端顯示它在其中一根線上接收到的字元(其中一些是控製字元,使其執行移動游標、更改顏色等操作)並在另一根線上發送與您鍵入的鍵相對應的字元。

像 xterm 這樣的終端仿真器並沒有什麼不同,只是它們不是線上路上發送和接收字元,而是在其文件描述符上讀取和寫入字元到主端。一旦他們產生了從終端,並在上面啟動了你的 shell,他們就不再碰它了。除了模擬這對線之外,xterm 還可以通過該文件描述符將某些線路規程屬性更改到主端。例如,他們可以更新大小屬性,以便將 SIGWINCH 發送到與從屬 pty 互動的應用程序,以通知它們更改的大小。

除此之外,終端/終端仿真器幾乎沒有智能

您寫入終端設備(如 pty 從站)的內容是您要在此處顯示的內容,從中讀取的內容是您在此處輸入的內容,因此終端仿真器讀取或寫入該設備沒有意義. 他們是另一端的人。


tty 線紀律

很多情報都在tty線紀律中。線路規程是一個軟體模組(位於驅動程序中,在核心中),位於該設備和線路/線路(pty 的主端)之間的串列/pty 設備之上。

串列線的另一端可以有一個終端,也可以是滑鼠或另一台用於聯網的電腦。例如,您可以附加一個 SLIP 線路規程以在串列設備(或 pty 設備)之上獲取網路介面,或者您可以擁有一個tty線路規程。tty 線路規程是至少在 Linux 上用於串列和 pty 設備的預設線路規程。在 Linux 上,您可以使用ldattach.

您可以通過發出命令來查看禁用 tty 行規則的效果stty raw -echo(注意 bash 提示符或其他互動式應用程序,例如vi將終端設置為所需的確切模式,因此您想使用類似的啞應用程序cat來體驗)。然後,寫入從終端設備的所有內容都會立即發送到主設備以供 xterm 讀取,並且 xterm 寫入主設備的每個字元都可以立即可供從設備讀取。

線路規程是實現終端設備內部線路編輯器的地方。例如stty icanon echo(預設情況下),當您鍵入 時a,xterm 會寫入a主伺服器,然後行規則將其顯(使 aa可用於xterm顯示以供閱讀),但不會使任何內容可用於從機端讀取. 然後,如果您鍵入退格鍵,xterm 發送一個^?or^H字元,行規則(如^?or^H對應於行規則設置)發送erase回 master a ^Hspace^H刪除xterm``a您剛剛在它的螢幕上輸入了內容,但仍然沒有向從從端讀取的應用程序發送任何內容,它只是更新其內部行編輯器緩衝區以刪除a您之前輸入的內容。

然後,當您按 Enter 鍵時,xterm 發送^M(CR),該行規則將輸入轉換為 ^J (LF),並將您目前輸入的內容髮送到從屬端讀取(正在讀取的應用程序/dev/pts/x將接收你已經輸入了包括 LF,但不是a因為你已經刪除了它),而在主端,它發送一個 CR 和 LF 將游標移動到下一行和螢幕的開頭。

線路紀律還負責在收到主控端的字元等時向終端的前台程序組****發送信號。SIGINT^C

許多互動式終端應用程序禁用了該行學科的大部分*功能以自行實施。*但無論如何,請注意終端 ( xterm) 幾乎沒有參與其中(除了顯示它被告知要顯示的內容)。

每個程序和每個終端設備只能有一個會話。會話可以附加一個控制終端,但不是必須的(所有會話在沒有終端的情況下開始,直到它們打開一個終端)。xterm,在它派生來執行你的 shell 的過程中,通常會創建一個新會話(因此從你啟動的終端中分離(xterm如果有的話))/dev/pts/x,通過將該終端設備附加到新會話來打開它產生的新會話。然後它將在該程序中執行您的 shell,因此您的 shell 將成為會話負責人。您的 shell 或該會話中的任何互動式 shell 通常會處理程序組和tcsetpgrp(), 來設置該終端的前台和後台作業。

至於具有 tty 規則(串列或 pty)的終端設備儲存了哪些資訊,這通常是stty命令顯示和修改的內容。所有學科配置:終端螢幕大小、本地、輸入輸出標誌、特殊字元設置(如 ^C、^Z…)、輸入和輸出速度(與 ptys 無關)。這對應於 Linux上映射到/ ioctls的tcgetattr()/函式和/用於螢幕大小。您可能會爭辯說,目前前台程序組是儲存在終端設備(/ 、ioctls)或目前輸入或輸出緩衝區中的另一個資訊。tcsetattr()``TCGETS``TCSETS``TIOCGWINSZ``TIOCSWINSZ``tcsetpgrp()``tcgetpgrp()``TIOC{G,S}PGRP

請注意,終端設備中儲存的螢幕尺寸資訊可能無法反映真實情況。終端仿真器通常會在調整其視窗大小時設置它(通過主大小上的相同 ioctl),但如果應用程序在從屬端呼叫 ioctl 或未傳輸調整大小時(以防萬一),它可能會不同步一個 ssh 連接,這意味著另一個 pty 由sshdifssh忽略SIGWINCH例如)。一些終端也可以通過轉義序列查詢它們的大小,因此應用程序可以通過這種方式查詢它,並使用該資訊更新線路規則。

有關更多詳細資訊,您可以查看Debian 上的手冊頁termios和手冊頁。tty_ioctl

與其他線學科一起玩:

  1. 用偽終端模擬滑鼠:
socat pty,link=mouse fifo:fifo
sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
xinput list # see the new mouse there
exec 3<> fifo
printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right

上面,pty 的主端由 socat 終止到命名管道 ( fifo) 上。我們將該先進先出連接到寫入 0x87 0x0a 0x00 的程序(shell),這在滑鼠系統協議中表示no button pressed, delta(x,y) = (10,0). 在這裡,我們(外殼)不是模擬終端,而是滑鼠,我們發送的 3 個字節不會被終端設備的應用程序讀取(可能轉換)(mouse上面是某個設備的符號socat連結/dev/pts/x) ,但將被解釋為滑鼠輸入事件。 2. 創建一個 SLIP 介面:

# on hostA
socat tcp-listen:12345,reuseaddr pty,link=interface
# after connection from hostB:
sudo ldattach SLIP interface
ifconfig -a # see the new interface there
sudo ifconfig sl0 192.168.123.1/24

# on hostB
socat -v -x pty,link=interface tcp:hostA:12345
sudo ldattach SLIP interface
sudo ifconfig sl0 192.168.123.2/24
ping 192.168.123.1 # see the packets on socat output

上面,串列線被模擬socat為 hostA 和 hostB 之間的 TCP 套接字。SLIP 線路規程將通過該虛擬線路交換的那些字節解釋為 SLIP 封裝的 IP 數據包,以便在sl0介面上傳遞。

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