歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 如何改造 Linux 虛擬終端顯示文字

如何改造 Linux 虛擬終端顯示文字

日期:2017/2/28 14:55:53   编辑:Linux教程

簡介: 本文就 CJKTTY 補丁如何讓 linux 虛擬終端顯示漢字的原理進行了討論,為此介紹了 Linux 虛擬終端和其依賴的硬件的工作原理。過程中我們分析了 Linux 字符終端的不足之處,並向讀者介紹前沿的 Wayland system compositor 是什麼以及為什麼 需要它。

CJKTTY 補丁是什麼,為什麼我寫了它

當你不使用 X 的時候,打開電腦,你就在使用虛擬終端。這麼多年來它工作的很好,直到它來到了中國。包含中文字符的文件名無法正確顯示,中文文檔無法閱讀。當然可以使用 X , 但是我為什麼不能讓終端也能顯示漢字呢?如果在 X 下我能讓屏幕顯示漢字,終端下一定也能。為此我開始了 internet 上的搜尋。我找到了 fbterm,這是個可以利用 /dev/fb0 實現的終端模擬器,和 XTERM 一樣,只不過 XTERM 利用的 X 繪制文字,而 fbterm 直接寫入 /dev/fb0。

/dev/fb0 是什麼?

幀緩沖區設備。幀緩沖區是一塊存儲區域(內存或者顯存或者其他的輸出設備的存儲空間),內核將其抽象為一個設備。通過訪問該設備就能訪問幀緩沖區。幀緩沖區的內容既是屏幕映像。由輸出設備不停的掃描幀緩沖區生成顯示設備的控制信號。

然而我似乎總是忘記登錄後開啟 fbterm,對我來說,等看到亂碼的時候突然想起沒有開啟 fbterm 並不是那麼愉快的經歷。這只是其中一個缺點。fbterm 占用了幀緩沖區設備,導致 w3m 這類使用幀緩存繪制圖像的終端 www 浏覽器不能正常工作。許多依賴幀緩沖區設備的終端程序都不能被 fbterm 良好的兼容。於是我繼續尋找,找到了 youbest 寫的中文補丁。我有個喜歡使用最新內核的習慣,當內核升級導致 youbest 的補丁再也不能使用的時候,我開始到 youbest 發布補丁的頁面留言,希望 youbest 百忙中能修改一下他的補丁。

Youbest 似乎很忙,在新內核的誘惑下,我決定自己在修改。那個時候我才真正的開始看內核的代碼。終於了解了虛擬終端的工作原理後,我開始修改內核。由於內核內部結構變動導致 youbest 的補丁無法應用,我幾乎是從頭開始了開發而不是簡單的將無法應用的部分進行修整。唯一得到保留的就是 youbest 補丁中的點陣字庫。我將其命名為 CJKTTY , 取能顯示 CJK 的 TTY 之意。

從那裡獲得中文顯示補丁呢?

我將補丁托管在了 http://repo.or.cz/w/linux-2.6/cjktty.git,依據你使用的內核版本,簽出內核版本 -utf8 分支就可以。

控制台是如何顯示文字呢?

那麼,為了能在控制台下顯示出漢字到底需要做什麼樣的修改麼?在開始前,我想先介紹一些名字,並介紹一些控制台在硬件上是如何進行文字顯示的。首先我解釋一下幾個名詞,知道的人可以到這裡開始閱讀。

UNICODE

為每一個字符分配全球唯一的一個數字,但是並沒有規定這個數字的表示方法。數字的表示方法由 UTF 規范規定。UTF-16 使用 2 個字節表示一個 UNICODE 數字,但是對於 >=216的數字使用 4 字節來表達。UTF-8 則對於 <127 的數字采取單字節表示,大於 127 的數字要根據其大小選擇 2~6 個字節進行表示。UNICODE 在程序內部則簡單的使用 unsigned long 即可表示一個字符。

GLYPH

GLYPH 指的是字體裡的字形。字符總是要在特定的字體下表示的,該表示就是字形。比如一個只包含 26 個大小寫字母的字體,只包含了 52 個字形,如果該字體是先大寫後小寫排列的,那麼數字 0 就表示字形 'A' , 數字 1 就表示字形 'B'。UNICODE 或者 ASCII 到 GLYPH 的映射是由一個稱作 CMAP 的映射表做的。如果字體裡字符就是按照 UNICODE 排列的,則其 CMAP 就是 UNICODE CMAP。同理也有 ASCII CMAP。 VGA 自帶字體沒有提供 CMAP,操作系統假定它的 CMAP 是 ASCII CMAP。事實上也是如此。

TTY

內核為終端提供的接口,對應用程序而言就是 TTY 設備。通常是使用 stdin stdout 來訪問。TTY 提供各種 IOCTL 用來設置終端的模式。TTY 也提供了用戶控制程序的方法,比如 Ctrl-C 終止當前程序。 TTY 可以是顯示器 + 鍵盤構成的控制台,也可以是串口(可以通過貓鏈接到電話線上),可以通過 pts 模擬。XTERM 即利用 pts 為裡面運行的程序提供的模擬的終端 , 對應的設備文件 /dev/pts/* 由模擬終端程序動態創建。

控制台 (CONSOLE)

控制台特指由顯示器 + 鍵盤構成的終端。其中顯示器由顯卡控制,而且當前 VGA 兼容顯卡有兩種模式,文字模式和圖形模式。Linux 即可以使用文字模式也可以使用圖形模式。

控制台對於程序是無法訪問的,程序只能通過虛擬終端使用控制台

虛擬終端 (VT)

如果你的電腦只有一個終端,那將是多麼乏味。一個需要長時間執行的任務就能導致你什麼也做不了,Linux 的多任務機制的好處蕩然無存。所以,你需要更多的終端。Linux 內核使用復用機制,將一個控制台復用為多個終端 (63 個,/dev/tty1 到 dev/tty63)。按鍵 Alt+F1-F12 ( 如果當前在 X 中,需要再按下 Ctrl 鍵 ) 能在 12 個終端中進行切換。事實上你擁有 63 個終端,鍵盤只能切換其中的 12 個,其他的終端你可以通過 chvt 命令進行切換。

當前擁有顯示器和鍵盤的虛擬終端被稱為活動終端或者當前終端。

TTY、控制台和虛擬終端有啥區別和聯系?

當你按下 Ctrl-C 的時候,當前執行的程序會被終止。因為 Linux 發送了 SIGTERM 信號給此終端的前台程序。該信號並不是由 Shell 產生,而是內核。不論是在虛擬終端下,還是在 X 裡的終端模擬器裡,這個功能都是一樣的。終端的一大功能就是進行任務控制,另一個功能是輸入輸出。輸入輸出模式下,還可以選擇行編輯模式,回顯模式,設置終端速率等等。不管你使用的是何種終端,這些功能都是存在的,因為他們都是一個類型的設備。內核將他們抽象為 TTY 設備。也就是說,應用程序都是在和 TTY 這個抽象層打交道,而不是和具體的設備打交道。能作為 TTY 的設備除了控制台外,還有串口。將兩台電腦的串口連接起來,其中一台電腦為串口打開登錄程序(執行 /sbin/agetty ttyS0 38400),另一台就能通過可以進行串口通信的程序 ( 比如 putty、minicom) 登錄對方。控制台可以作為 TTY 設備,但是一台電腦一般只有一個屏幕,也就使用一個控制台,所以 Linux 在控制台和 TTY 之間加了一層虛擬終端。由虛擬終端將控制台復用,這樣就可以使用多個終端而不是只有一個了。多個虛擬終端設備合作使用一個控制台。除了串口和虛擬終端,這些都是在內核實現的 TTY 設備,內核還提供了一個叫 PTY 的為終端設備,XTERM 之類的程序利用 PTY 提供的功能可以在程序裡實現 TTY 的功能。那麼,虛擬終端就是利用控制台復用出了多個 TTY 。TTY 邏輯由 TTY 子系統完成,復用邏輯由虛擬終端實現,而具體的顯示則交給控制台完成。如果說這是一個觀察者模型的話,控制台就是觀察者,它將虛擬終端的內容呈現到屏幕上。 在 Linux 下,控制台分文字模式控制台(vgacon)和圖形模式控制台 (fbcon)。

文字模式控制台 (VGA 文字模式 )

文字模式控制台使用 VGA 兼容顯卡的文字模式實現 VGA 兼容顯卡初始化時默認就處於文字模式,能顯示 80x25 個字符。

在文字模式下,顯卡雖然輸出給顯示器的是圖像,但是顯卡提供給內核的卻只能顯示文字功能。要顯示一個字符,內核將要顯示的字符的代碼和屬性寫入字符緩沖區相應地址即可。緩沖區如下面所示:


圖 1. 緩沖區


表 1. 每個字符的格式

屬性字節字符字節 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 閃爍 背景色 前景色 GLYPH

VGA 顯卡處於文字模式時,物理地址 0xB8000 即文字緩沖區起始地址,大小由其文字模式決定,最大 32KB 。VGA 顯卡內建字符發生器,不斷的掃描字符緩沖區並將文字轉換為圖形驅動顯示器顯示。其 GLYPH 即為字符的 ASCII 碼。

字符發生器和字體

字符發生器內建一個或者多個位圖字體。使用何種字體取決於設置的文字模式代碼。Linux 默認使用 80x25 字符 16 色模式 , 每字符 8x16 點陣。字符發生器的字體包含 256 個字形。字符發生器裡的文字和字符的對應關系在 DOS 系統下被稱為代碼頁。顯��自帶的被稱為 OEM 代碼頁。

字符發生器的字體可以修改。DOS 下通過修改代碼頁實現。Linux 下可以使用 setfont。

因為這一歷史原因,VGA 的文字模式最多同屏出現 256 種不同的字符。對於只有 26 個字母的拉丁文字綽綽有余,但是卻無法滿足擁有上萬字符的中文。文字模式控制台由 vgacon (drivers/video/console/vgacon.c)實現。 VGA 還有不常使用的單色文字模式,起始地址為 0xB0000 。並且字符格式也有所不同,這裡不再介紹。

圖形模式控制台

圖形模式控制台直接操作幀緩沖區顯示文字。幀緩沖區是一塊存儲區域(通常是在顯存中),其內容就是顯示在屏幕上的圖像。顯卡直接將其內容轉化為顯示器控制信號。對於程序而言,幀緩沖區就是屏幕。

圖像模式控制台使用幀緩沖區作為屏幕輸出,要想使用圖像模式控制台,必須加載幀緩沖區驅動並有相應的硬件。

不同的顯示設備通常使用不同的幀緩沖區驅動,對於 VGA 兼容顯卡,除了能使用針對顯卡寫的幀緩沖區驅動 ( 如果有的話 ),還可以使用通用的 VESA 驅動。 VESA 驅動利用 VGA 兼容的顯卡的 BIOS 將顯卡轉入 VGA 圖形模式並設置期望的緩沖區模式,由顯示模式內核參數 vga= 給出。 VGA 圖形模式下,幀緩沖區的起始地址為 0xA0000 ,最大 64KB 大小。像素格式看顯示色深。典型的 256 色模式下每像素一個字節。如果 BIOS 支持 VBE 擴展,能設置更大的分辨率和色彩深度,幀緩沖區大小也會超過 64KB,因而起始地址也不再是 0xA0000,具體細節請參考 維基百科. 幀緩存模式下,Linux 內核將需要顯示的字符首先轉換為位圖,然後將位圖字體寫入幀緩存即可變呈現於屏幕。也就是說,圖形模式下,由內核來承擔字符發生器的工作。理論上來說,這個內核自帶的字符發生器將能支持顯示多於 255 種字符。但是我將在後面告訴讀者,因為歷史原因,內核實現的字符發生器和 VGA 的字符發生器有著一樣的缺點。圖形控制台由 fbcon(drivers/video/console/fbcon.c)實現。圖形控制台由於需要生成位圖字形,需要帶上位圖字體,編譯內核的時候至少需要選擇一個字體。位圖字體在內核是一個大數組,不同的字體 ( drivers/video/console/font_* ) 存儲在各自的數組中。

Copyright © Linux教程網 All Rights Reserved