終端和外殼如何交換數據?
在 Linux 中,終端與 Shell 相關聯。終端將輸入發送到 Shell(例如:)
pwd
,Shell 將輸出發送回終端(例如:)/home/paul
。此圖顯示了終端和 Shell 之間的關係(假設我使用的終端是
gnome-terminal
,而 Shell 是bash
):現在我想知道的是終端和外殼使用什麼機制來交換數據。這就是我認為發生的事情:
- 執行時
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 文件,但邏輯仍然是相同的。
你錯過了一個必要的部分。偽 tty 設備不像套接字那樣對稱。有主端和從端。中的文件
/dev/pts
代表從設備。終端仿真器通過呼叫創建一個偽 tty
openpty
(或者對於您想要在新 tty 上執行新程序的常見情況,forkpty
這是openpty
額外的一些設置)。在較低級別,這涉及打開/dev/ptmx
並執行一些魔術 ioctl。通過呼叫
openpty
終端仿真器得到一對文件描述符,並且還可以得到/dev/pts
slave對應的文件名。主程序沒有單獨的名稱,因為從不需要子程序按名稱打開它。主設備和從設備的行為確實有點像套接字的兩端:你在一端寫入的內容是從另一端讀取的。但是因為這是一個 tty,所以所有的 tty 模式都適用於通過的數據。
例如,如果您是終端仿真器,並且您收到按鍵的
A
按鍵,您應該寫入'a'
主文件描述符。這直接相當於通過串列線從終端向電腦發送該字節。它將導致'a'
從從站讀取(通過正在讀取它的任何程序 - 例如外殼)。
D
如果您在按鍵按下時收到按鍵按下Ctrl
,您應該將一個4
字節 ('D' ^ 0x40
) 寫入主文件描述符。(因為那是真正的終端線上路上發送的內容。)接下來發生的事情取決於 tty 模式。在原始模式下,讀取從 tty 的程序將看到一個4
字節。在熟模式下,tty 將啟動“EOF 特殊鍵按下”行為。在反方向,也有一些處理。當某些程序寫入從 tty 時,由於後處理
'\n'
,您可能會"\r\n"
在主文件描述符上收到。onlcr
歷史部分,無聊請跳過
很久以前,從設備的名稱為like
/dev/ttyp0
,每個設備都有一個對應的主設備,如/dev/ptyp0
。它們不是動態創建的。終端仿真器可以對它們全部進行探測以找到目前未使用的一個,然後開始使用它。管理所有權和權限是一個問題。xterm
是 setuid-root 只是為了它可以 chown 奴隸。名為“UNIX98 ptys”的新方案通過神奇的 ioctl 處理設備創建和所有權,因此文件僅
/dev/pts
在使用時出現,並且歸執行創建它們的程序的使用者所有。