Linux 終端(TTY)
- 2019 年 10 月 3 日
- 筆記
TTY 是 Teletype 或 Teletypewriter 的縮寫,原來是指電傳打字機,後來這種設備逐漸鍵盤和顯示器取代。不管是電傳打字機還是鍵盤顯示器,都是作為計算機的終端設備存在的,所以 TTY 也泛指計算機的終端(terminal)設備。為了支持這些 TTY 設備,Linux 實現了一個叫做 TTY 的子系統。所以 TTY 既指終端,也指 Linux 的 TTY 子系統,當然 TTY 還有更豐富(混亂)的含義,本文試圖把它們解釋清楚。本文中演示部分使用的環境為 ubuntu 18.04。
硬件終端 terminal(TTY)
早期的終端(terminal) 是一台獨立於計算機的機器(teletype 即, TTY),大概像下面的樣子:
它終端通過線纜與計算機連接,並完成計算機的輸入輸出功能:
現在物理終端實際上已經滅絕了,我們看到的所有 TTY 都是模擬視頻終端,即軟件仿真出來的終端。可以通過 toe -a 命令查看系統支持的終端類型,不要奇怪,這是一個挺長的列表。
控制台 console
提到終端就不能不提控制台 console。控制台的概念與終端含義非常相近,其實現在我們經常用它們表示相同的東西,但是在計算機的早期時代,它們確實是不同的東西。
一些數控設備(比如數控機床)的控制箱,通常會被稱為控制台,顧名思義,控制台就是一個直接控制設備的面板,上面有很多控制按鈕。 在計算機里,把那套直接連接在電腦上的鍵盤和顯示器就叫做控制台。而終端是通過串口連接上的,不是計算機自身的設備,而控制台是計算機本身就有的設備,一個計算機只有一個控制台。計算機啟動的時候,所有的信息都會顯示到控制台上,而不會顯示到終端上。這同樣說明,控制台是計算機的基本設備,而終端是附加設備。計算機操作系統中,與終端不相關的信息,比如內核消息,後台服務消息,都可以顯示到控制台上,但不會顯示到終端上。比如在啟動和關閉 Linux 系統時,我們可以在控制台上看到很多的內核信息(下圖來自 vSphere Client 中的 “Virtual Machine Console”):
現在終端和控制台都由硬件概念,逐漸演化成了軟件的概念。簡單的說,能直接顯示系統消息的那個終端稱為控制台,其他的則稱為終端(控制台也是一個終端)。或者我們在平時的使用中壓根就不區分 Linux 中的終端與控制台。
下面的例子是通過 /dev/console 文件向控制台發送消息,這個這個例子我們可以看到控制台與終端的一點點不同之處。
打開 vSphere Client 中的 “Virtual Machine Console”(即控制台),默認顯示的是 tty1:
通過其他的終端向 /dev/console 中寫入字符串 “hello world”:
root@esearch:~# echo “hello world” > /dev/console
字符串顯示在了控制台中。然後通過 Ctrl + Alt + F2 把控制台中的終端切換到 tty2,再次向 /dev/console 寫入字符串:
root@esearch:~# echo “hello world” > /dev/console
這次字符串寫到了 tty2 中,這說明 Linux 總是把寫入 /dev/console 的內容會顯示在控制台中當前的虛擬終端(tty1-tty6)里。
TTY 設備
從歷史上看,終端剛開始就是終端機,配有打印機,鍵盤,帶有一個串口,通過串口傳送數據到主機端,然後主機處理完交給終端打印出來。電傳打字機(teletype)可以被看作是這類設備的統稱,因此終端也被簡稱為 TTY(teletype 的縮寫)。
如下圖所示(下圖來自互聯網):
UART 驅動
如上圖所示,物理終端通過電纜連接到計算機上的 UART(通用異步接收器和發射器)。操作系統中有一個 UART 驅動程序用於管理位元組的物理傳輸。
行規範
上圖中內核中的 Line discipline(行規範)用來提供一個編輯緩衝區和一些基本的編輯命令(退格,清除單個單詞,清除行,重新打印),主要用來支持用戶在輸入時的行為(比如輸錯了,需要退格)。
TTY 驅動
TTY 驅動用來進行會話管理,並且處理各種終端設備。
UART 驅動、行規範和 TTY 驅動都位於內核中,它們的一端是終端設備,另一端是用戶進程。因為在 Linux 下所有的設備都是文件,所以它們三個加在一起被稱為 “TTY 設備”,即我們常說的 TTY。
從軟件仿真終端到偽終端
後來的終端慢慢演變成了鍵盤 + 顯示器。如果我們要把內容輸出到顯示器,只要把這些內容寫入到顯示器對應的 TTY 設備就可以了,然後由 TTY 層負責匹配合適的驅動完成輸出,這也是 Linux 控制台的工作原理(下圖來自互聯網):
上圖中,TTY 驅動和行規範的行為與前面的示例類似,但不再有 UART 或物理終端。相反,軟件仿真出視頻終端,並最終被渲染到 VGA 顯示器。注意,這裡出現了軟件仿真終端,它們是運行在內核態的。顯示器和 vSphere Client “Virtual Machine Console” 中的 tty1-tty6 都是軟件仿真終端:
/dev/tty1-/dev/tty6 是這些仿真終端在文件系統中的表示,程序通過對這些文件的讀寫實現對仿真終端的讀寫。
如果我們在用戶空間也進行終端仿真,情況會變得更加靈活,下圖是 xterm 及其克隆的工作方式(下圖來自互聯網):
為了便於將終端仿真移入用戶空間,同時仍保持 TTY 子系統(TTY 子系統指 TTY 驅動和行規範)的完整,偽終端被發明了出來(pseudo terminal 或 pty)。偽終端在內核中分為兩部分,分別是 master side 和 在 TTY 驅動中實現的 slave side。注意上圖中的 xterm,這是一個運行在用戶態的終端仿真程序,比如 Ubuntu Desktop 中的 GNOME Terminal:
當創建一個偽終端時,會在 /dev/pts 目錄下創建一個設備文件:
如果是通過 PuTTY 等終端仿真程序通過 SSH 的方式遠程連接 Linux,那麼終端仿真程序通過 SSH 與 PTY master side 交換數據。
終端與偽終端的區別
至此我們可以得出這樣的結論:現在所說的終端已經不是硬件終端了,而是軟件仿真終端(終端模擬軟件)。
關於終端和偽終端,可以簡單的理解如下:
- 真正的硬件終端基本上已經看不到了,現在所說的終端、偽終端都是軟件仿真終端(即終端模擬軟件)
- 一些連接了鍵盤和顯示器的系統中,我們可以接觸到運行在內核態的軟件仿真終端(tty1-tty6)
- 通過 SSH 等方式建立的連接中使用的都是偽終端
- 偽終端是運行在用戶態的軟件仿真終端
總結
通過本文我們可以了解到,真正的硬件終端基本上已經看不到了。在一些連接了鍵盤和顯示器的系統中(當然也包括一些 vsphere 等虛擬環境),我們可以接觸到運行在內核態的軟件仿真終端。而我們使用最多的則是偽終端。
參考:
解密TTY
Linux TTY/PTS概述
The TTY demystified
What is stored in /dev/pts files and can we open them?
終端、虛擬終端、shell、控制台、tty的區別