簡(jiǎn)介: 本文就 CJKTTY 補(bǔ)丁如何讓 linux 虛擬終端顯示漢字的原理進(jìn)行了討論,為此介紹了 Linux 虛擬終端和其依賴(lài)的硬件的工作原理。過(guò)程中我們分析了 Linux 字符終端的不足之處,并向讀者介紹前沿的 Wayland system compositor 是什么以及為什么 需要它。
CJKTTY 補(bǔ)丁是什么,為什么我寫(xiě)了它
當(dāng)你不使用 X 的時(shí)候,打開(kāi)電腦,你就在使用虛擬終端。這么多年來(lái)它工作的很好,直到它來(lái)到了中國(guó)。包含中文字符的文件名無(wú)法正確顯示,中文文檔無(wú)法閱讀。當(dāng)然可以使用 X , 但是我為什么不能讓終端也能顯示漢字呢?如果在 X 下我能讓屏幕顯示漢字,終端下一定也能。為此我開(kāi)始了 internet 上的搜尋。 我找到了 fbterm,這是個(gè)可以利用 /dev/fb0 實(shí)現(xiàn)的終端模擬器,和 XTERM 一樣,只不過(guò) XTERM 利用的 X 繪制文字,而 fbterm 直接寫(xiě)入 /dev/fb0。
/dev/fb0 是什么?
幀緩沖區(qū)設(shè)備。幀緩沖區(qū)是一塊存儲(chǔ)區(qū)域(內(nèi)存或者顯存或者其他的輸出設(shè)備的存儲(chǔ)空間),內(nèi)核將其抽象為一個(gè)設(shè)備。通過(guò)訪問(wèn)該設(shè)備就能訪問(wèn)幀緩沖區(qū)。幀緩沖區(qū)的內(nèi)容既是屏幕映像。由輸出設(shè)備不停的掃描幀緩沖區(qū)生成顯示設(shè)備的控制信號(hào)。
然而我似乎總是忘記登錄后開(kāi)啟 fbterm,對(duì)我來(lái)說(shuō),等看到亂碼的時(shí)候突然想起沒(méi)有開(kāi)啟 fbterm 并不是那么愉快的經(jīng)歷。這只是其中一個(gè)缺點(diǎn)。fbterm 占用了幀緩沖區(qū)設(shè)備,導(dǎo)致 w3m 這類(lèi)使用幀緩存繪制圖像的終端 www 瀏覽器不能正常工作。許多依賴(lài)幀緩沖區(qū)設(shè)備的終端程序都不能被 fbterm 良好的兼容。 于是我繼續(xù)尋找,找到了 youbest 寫(xiě)的中文補(bǔ)丁。 我有個(gè)喜歡使用最新內(nèi)核的習(xí)慣,當(dāng)內(nèi)核升級(jí)導(dǎo)致 youbest 的補(bǔ)丁再也不能使用的時(shí)候,我開(kāi)始到 youbest 發(fā)布補(bǔ)丁的頁(yè)面留言,希望 youbest 百忙中能修改一下他的補(bǔ)丁。
Youbest 似乎很忙,在新內(nèi)核的誘惑下,我決定自己在修改。那個(gè)時(shí)候我才真正的開(kāi)始看內(nèi)核的代碼。終于了解了虛擬終端的工作原理后,我開(kāi)始修改內(nèi)核。由于內(nèi)核內(nèi)部結(jié) 構(gòu)變動(dòng)導(dǎo)致 youbest 的補(bǔ)丁無(wú)法應(yīng)用,我?guī)缀跏菑念^開(kāi)始了開(kāi)發(fā)而不是簡(jiǎn)單的將無(wú)法應(yīng)用的部分進(jìn)行修整。唯一得到保留的就是 youbest 補(bǔ)丁中的點(diǎn)陣字庫(kù)。我將其命名為 CJKTTY , 取能顯示 CJK 的 TTY 之意。
從那里獲得中文顯示補(bǔ)丁呢?
我將補(bǔ)丁托管在了 ,依據(jù)你使用的內(nèi)核版本,簽出內(nèi)核版本 -utf8 分支就可以。
控制臺(tái)是如何顯示文字呢?
那么,為了能在控制臺(tái)下顯示出漢字到底需要做什么樣的修改么?在開(kāi)始前,我想先介紹一些名字,并介紹一些控制臺(tái)在硬件上是如何進(jìn)行文字顯示的。 首先我解釋一下幾個(gè)名詞,知道的人可以到這里開(kāi)始閱讀。
UNICODE
為每一個(gè)字符分配全球唯一的一個(gè)數(shù)字,但是并沒(méi)有規(guī)定這個(gè)數(shù)字的表示方法。數(shù)字的表示方法由 UTF 規(guī)范規(guī)定。UTF-16 使用 2 個(gè)字節(jié)表示一個(gè) UNICODE 數(shù)字,但是對(duì)于 >=216的數(shù)字使用 4 字節(jié)來(lái)表達(dá)。UTF-8 則對(duì)于 <127 的數(shù)字采取單字節(jié)表示,大于 127 的數(shù)字要根據(jù)其大小選擇 2~6 個(gè)字節(jié)進(jìn)行表示。UNICODE 在程序內(nèi)部則簡(jiǎn)單的使用 unsigned long 即可表示一個(gè)字符。
GLYPH
GLYPH 指的是字體里的字形。字符總是要在特定的字體下表示的,該表示就是字形。比如一個(gè)只包含 26 個(gè)大小寫(xiě)字母的字體,只包含了 52 個(gè)字形,如果該字體是先大寫(xiě)后小寫(xiě)排列的,那么數(shù)字 0 就表示字形 'A' , 數(shù)字 1 就表示字形 'B'。UNICODE 或者 ASCII 到 GLYPH 的映射是由一個(gè)稱(chēng)作 CMAP 的映射表做的。如果字體里字符就是按照 UNICODE 排列的,則其 CMAP 就是 UNICODE CMAP。同理也有 ASCII CMAP。 VGA 自帶字體沒(méi)有提供 CMAP,操作系統(tǒng)假定它的 CMAP 是 ASCII CMAP。事實(shí)上也是如此。
TTY
內(nèi)核為終端提供的接口,對(duì)應(yīng)用程序而言就是 TTY 設(shè)備。通常是使用 stdin stdout 來(lái)訪問(wèn)。TTY 提供各種 IOCTL 用來(lái)設(shè)置終端的模式。TTY 也提供了用戶(hù)控制程序的方法,比如 Ctrl-C 終止當(dāng)前程序。 TTY 可以是顯示器 + 鍵盤(pán)構(gòu)成的控制臺(tái),也可以是串口(可以通過(guò)貓鏈接到電話(huà)線(xiàn)上),可以通過(guò) pts 模擬。XTERM 即利用 pts 為里面運(yùn)行的程序提供的模擬的終端 , 對(duì)應(yīng)的設(shè)備文件 /dev/pts/* 由模擬終端程序動(dòng)態(tài)創(chuàng)建。
控制臺(tái) (CONSOLE)
控制臺(tái)特指由顯示器 + 鍵盤(pán)構(gòu)成的終端。其中顯示器由顯卡控制,而且當(dāng)前 VGA 兼容顯卡有兩種模式,文字模式和圖形模式。Linux 即可以使用文字模式也可以使用圖形模式。
控制臺(tái)對(duì)于程序是無(wú)法訪問(wèn)的,程序只能通過(guò)虛擬終端使用控制臺(tái)
虛擬終端 (VT)