校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > Linux內(nèi)核如何輸出中文字符的方法示例

Linux內(nèi)核如何輸出中文字符的方法示例

熱門標(biāo)簽:虛假地圖標(biāo)注 靈圖uu電子寵物店地圖標(biāo)注 濮陽好的聯(lián)通400電話申請 地圖標(biāo)注黃河的位置 山東企業(yè)外呼系統(tǒng)公司 地圖標(biāo)注如何改成微信號 400電話號碼辦理多少錢 百度地圖標(biāo)注公司位置要多少錢 承德地圖標(biāo)注公司

你在Windows/MacOS的登錄Linux的SSH終端上很容易輸入中文并且獲得中文輸出,比如下面這樣:

但是卻幾乎不可能將中文顯示在Linux自身的 虛擬終端 上:

[root@localhost font]# echo 皮鞋 >/dev/tty2

顯示了兩個(gè)問號,顯然Linux內(nèi)核并不能識別中文。

為什么說是Linux內(nèi)核不能識別中文呢?這里需要理清一個(gè)關(guān)系:

  • 你在遠(yuǎn)程SSH終端上的輸入和顯示輸出的行為,都是SSH終端的宿主機(jī)完成的,比如Windows,MacOS,和Linux無關(guān)。
  • 你在Linux本地虛擬終端,比如/dev/tty1上的輸入和顯示輸出行為,則是由Linux內(nèi)核自己處理的。

比如,我在MacOS用iTerm SSH連接到了一個(gè)遠(yuǎn)程CentOS Linux,iTerm上的所有的鍵盤輸入,顯示器輸出行為都是iTerm的這臺MacOS宿主機(jī)完成的。

相反,如果你直接在這臺CentOS Linux的虛擬終端上輸入并且企圖獲得輸出,那么這個(gè)輸入輸出則必須由Linux內(nèi)核自身來處理。

基本上就這些。至于說為什么Linux內(nèi)核不支持中文,那要了解Linux內(nèi)核處理虛擬終端輸入輸出時(shí)是如何對待unicode的邏輯,這要涉及一大堆的理論知識,非常煩人。

反正我這里就是無法輸出中文,我也不是做這個(gè)的,顯然這不是一個(gè)必然要完成的工作任務(wù),所以,我只是玩玩。

本文的目標(biāo)就是要讓Linux的虛擬終端可以輸出中文。

僅僅是輸出中文,哪怕是一個(gè)中文漢字也好。具體來講,就是 當(dāng)我在鍵盤敲入'A'字符時(shí),顯示器回顯出來的是一個(gè)漢字。

所以說,本文并不打算 讓Linux內(nèi)核大規(guī)模完備地支持中文 ,這種事已經(jīng)有很多人和社區(qū)做了,但是可玩性并不高,畢竟這種事是可以當(dāng)私活兒賺錢的,只要是賺錢的活兒,可玩性就不高,因?yàn)橐炻铩?/p>

不需要懂冗長枯燥的unicode編碼,不需要懂枯燥的font字體格式,看看怎么玩。

先展示效果吧,下面是一個(gè)8×168\times 168×16的點(diǎn)陣?yán)樱?br />

不是很好看,于是就做了下面一個(gè)28×1628\times 1628×16的點(diǎn)陣:

下面說一下這是如何實(shí)現(xiàn)的。

從你敲鍵盤的某個(gè)按鍵開始,到某個(gè)字符最終顯示在虛擬終端的顯示器上,這期間其實(shí)有兩個(gè)映射:

鍵盤和字符集的映射

將某個(gè)按鍵事件轉(zhuǎn)換為某個(gè)字符集里的某個(gè)碼,比如當(dāng)按下'A'鍵時(shí),將其映射到0x41。

字符集和字體的映射

將某個(gè)字符集的碼字映射到某個(gè)點(diǎn)陣用來顯示。比如將0x41映射到能讓人看出來是一個(gè)字符'A'的樣子的8×168\times 168×16點(diǎn)陣。

Linux的console并不能識別超過0x00ff的字符集碼字,因此就不能處理碼字超過0x00ff的unicode,如果希望它能做到,這就要改內(nèi)核代碼了。

剛才說了,修改內(nèi)核代碼大規(guī)模全面支持中文,這是可以賺錢的事,不但沒意思,也沒人會(huì)分享。

所以我嘗試去修改上面的兩個(gè)映射來解決問題。由于只是顯示,所以我不會(huì)去修改 鍵盤和字符集的映射 ,因?yàn)槟菢尤匀粫?huì)碰到字符集碼字超過0x00ff的處理問題。

這意味著要想顯示中文,只剩下一條路,那就是修改 字符集和字體的映射 !

這個(gè)映射肯定是保存在內(nèi)核內(nèi)存或者文件系統(tǒng)的某個(gè)地方。我可以在當(dāng)前內(nèi)核的config文件里找到如下的信息:

[root@localhost font]# cat /boot/config-3.10.0-862.11.6.el7.x86_64 |grep FONT
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y

再去看/proc/kallsyms里有什么:

[root@localhost font]# cat /proc/kallsyms |grep font.*8x
ffffffffb006a3e0 R font_vga_8x8
ffffffffb006a420 r fontdata_8x8
ffffffffb006ac20 R font_vga_8x16
ffffffffb006ac60 r fontdata_8x16
ffffffffb0307a10 r __ksymtab_font_vga_8x16
ffffffffb03234b8 r __kcrctab_font_vga_8x16
ffffffffb034246e r __kstrtab_font_vga_8x16

嗯,這就是內(nèi)核里保存的字體:

[root@localhost rh]# ll ./drivers/video/console/font_8x*
-rw-r--r--. 1 root root 95976 Sep 17 2018 ./drivers/video/console/font_8x16.c
-rw-r--r--. 1 root root 50858 Sep 17 2018 ./drivers/video/console/font_8x8.c

這里不再分析這兩個(gè)文件。這里僅僅是確認(rèn)了一個(gè)事實(shí), 內(nèi)核在初始化的時(shí)候會(huì)使用自己的字體 ,這個(gè)時(shí)候畢竟除了內(nèi)核本身,什么都沒有。

問題是到了用戶態(tài),這個(gè)字體是可以被改變的,可以被改的花里胡哨的,這些個(gè)字體可不是僅僅兩個(gè)8x8和8x16就能hold住的…

這個(gè)時(shí)候就需要找我們安裝在發(fā)行版里面的字體文件了。我們要找到它,然后改掉里面的某個(gè)字體的形狀,將其變成中文!就這么簡單。

不必去搜這個(gè)字體文件安裝保存在什么地方,通過執(zhí)行strace setfont命令就能找到它。

[root@localhost ~]# strace -F -e trace=open setfont
...
strace: Process 6276 attached
[pid 6276] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
...
[pid 6276] open("/lib/kbd/consolefonts/default8x16.psfu.gz", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 4
[pid 6276] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6276, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

就是它了, /lib/kbd/consolefonts/default8x16.psfu.gz

也不必去搜psfu格式的字體的format,通過模式識別就能找到特定的字符。

我準(zhǔn)備先找到 ‘A',然后把它后面的'B'和'C'改成我的名字“趙”和“亞”。

首先我要把“趙”和“亞”字做出來,形成一個(gè)點(diǎn)陣。以下是我的作品“趙”:

00000000
00000000
00100000
11111000
00100101 
00100101
11111010
00100011 
00111010 
01100101 
01100000
10011000
10000111
00000000
00000000
00000000

下面就要用這個(gè)點(diǎn)陣替換'B'的點(diǎn)陣,同時(shí)制作一個(gè)“亞”字,替換'C'的點(diǎn)陣,

在下面的站點(diǎn)可以找到該default font的對應(yīng)點(diǎn)陣圖解:
https://www.zap.org.au/software/fonts/console-fonts-distributed/psftx-centos-7.5/default8x16.psfu.large.pdf

我們就可以得到該'A'字符的點(diǎn)陣數(shù)組,然后在default8x16.psfu文件里匹配這個(gè)數(shù)組就可以了。代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <string.h>

unsigned char zhaoya[32] = {
			// 第一行為“趙”
			0x00, 0x00, 0x20, 0xf8, 0x25, 0x25, 0xfa, 0x23, 0x3a, 0x65, 0x60, 0x98, 0x87, 0x00, 0x00, 0x00,
			// 第二行為亞
			0x00, 0x00, 0x00, 0x7e, 0x24, 0x24, 0x24, 0xa5, 0xa5, 0x66, 0x24, 0x24, 0x7e, 0x00, 0x00, 0x00
};


int main(int argc, char **argv)
{
	int i = 0;
	unsigned char buf[16];
	off_t offset = 0;
	int s = 0;

	int fd = open("default8x16.psfu", O_RDWR);
	i = pread(fd, buf, 8, offset);
	while (1) {
		i = pread(fd, buf, 16, offset);
		if (s == 2) { // 替換'C'
			memcpy (buf, &zhaoya[16], 16);
			i = pwrite(fd, buf, 16, offset);
			break;
		}
		if (s == 1) { // 替換'B'
			memcpy (buf, &zhaoya[0], 16);
			pwrite(fd, buf, 16, offset);
			s = 2;
		}
		// 簡易的方法識別到'A'
		if (buf[0] == 0x00 && buf[1] == 0x00 &&
			buf[2] == 0x10 && buf[3] == 0x38) {
			printf("A found at %d !\n", offset);
			s = 1;
		}
		offset += 16;
	}
}

直接編譯執(zhí)行,然后將這個(gè)default8x16.psfu作為參數(shù)set到內(nèi)核即可:

[root@localhost font]# setfont ./default8x16.psfu

此時(shí)進(jìn)入Linux的虛擬終端tty2,當(dāng)敲鍵盤的大寫'B'時(shí),就會(huì)出現(xiàn)一個(gè)“趙”字。

雖然16×816\times 816×8甚至8×88\times 88×8也能做出復(fù)雜的中文點(diǎn)陣,但是這也太難看了。

于是我要找一個(gè)更高分辨率的font。我在Ubuntu上找到了一個(gè)高分辨率的28×1628\times 1628×16點(diǎn)陣 Arabic-VGA28x16.psf.gz 。修改它的方法和前面這個(gè)完全一樣,它的點(diǎn)陣圖如下:
https://www.zap.org.au/software/fonts/console-fonts-distributed/psftx-debian-9.4/Lat7-VGA28x16.psf.pdf

我不需要自己做28×1628\times 1628×16的點(diǎn)陣了,我只要用GNU uifont的現(xiàn)成的即可。直接在 unifont_sample-12.1.01.hex 里面按照“趙”和“亞”的unicode碼字就能索引到點(diǎn)陣。關(guān)于任意字符的unicode碼字的查詢,可以參見:
https://graphemica.com/

替換font的代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include "zhao"

#define L	28*2
int fd;

int main(int argc, char **argv)
{
	unsigned char buf[L];
	off_t offset = 0;
	// 這個(gè)0x0e60 就是模式匹配獲得的偏移。
	offset += 0x0e60;

	fd = open("Lat7-VGA28x16.psf", O_RDWR);
	pread(fd, buf, L, offset);
	memset(buf, 0, L);
	memcpy(buf+8, &code[0], 32);
	pwrite(fd, buf, L, offset);

	offset += L;
	pread(fd, buf, L, offset);
	memset(buf, 0, L);
	memcpy(buf+8, &code[32], 32);
	pwrite(fd, buf, L, offset);

	offset += L;
	pread(fd, buf, L, offset);
	memset(buf, 0, L);
	memcpy(buf+8, &code[64], 32);
	pwrite(fd, buf, L, offset);
}

然后它的效果就是:

還不錯(cuò)。

其實(shí)本文的內(nèi)容僅僅就是:

  1. 做一個(gè)蹩腳的點(diǎn)陣;
  2. keyboard,ascii/unicode,font之間的映射關(guān)系;
  3. 什么細(xì)節(jié)都不懂的情況下定位分析問題的方法;
  4. 越簡單越好,越復(fù)雜越糟糕。

嗯,其實(shí)第三點(diǎn)和第四點(diǎn)是最重要的。

最后,如果你想知道你當(dāng)前的虛擬終端支持那些字體,輸入:

[root@localhost font]# showconsolefont

就會(huì)顯示:

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

標(biāo)簽:德宏 泰安 上海 淮安 福州 鷹潭 安康 樂山

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Linux內(nèi)核如何輸出中文字符的方法示例》,本文關(guān)鍵詞  Linux,內(nèi)核,如何,輸出,中文,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Linux內(nèi)核如何輸出中文字符的方法示例》相關(guān)的同類信息!
  • 本頁收集關(guān)于Linux內(nèi)核如何輸出中文字符的方法示例的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    成人av在线一区二区三区| 国内精品在线播放| 美女视频黄a大片欧美| 成人免费视频免费观看| 日韩视频在线你懂得| 国产精品久久久久久久久快鸭 | 国产精品影音先锋| 欧美自拍偷拍一区| 国产午夜精品一区二区三区嫩草 | 欧美久久一区二区| 国产精品久久久久婷婷二区次| 青青草原综合久久大伊人精品 | 国产一区二区三区免费观看| 在线影视一区二区三区| 国产精品午夜在线| 国内外精品视频| 日韩一级二级三级精品视频| 国产精品国产三级国产专播品爱网 | 亚洲人成在线观看一区二区| 喷白浆一区二区| 欧美剧情片在线观看| 一区二区在线观看视频在线观看| 国产91精品欧美| 欧美精品一区二区三区久久久 | 99久久国产综合精品女不卡| 久久久美女毛片| 精品影视av免费| 亚洲精品一区二区三区精华液| 男女性色大片免费观看一区二区| 欧美高清视频在线高清观看mv色露露十八 | 国产精品剧情在线亚洲| 国产一区视频网站| 久久精品亚洲精品国产欧美| 久久97超碰国产精品超碰| 日韩视频一区二区| 久久99久久精品欧美| 欧美电影免费提供在线观看| 久草这里只有精品视频| 精品国产第一区二区三区观看体验| 久久国产精品色婷婷| 26uuu亚洲| 丁香啪啪综合成人亚洲小说| 国产精品激情偷乱一区二区∴| 91丝袜美腿高跟国产极品老师 | 久久aⅴ国产欧美74aaa| 亚洲精品一区在线观看| 成人免费视频app| 亚洲蜜桃精久久久久久久| 欧美影片第一页| 日韩高清不卡一区| 2020日本不卡一区二区视频| 丁香六月综合激情| 一区二区高清视频在线观看| 91精品国产综合久久小美女| 国产乱码精品一品二品| 亚洲视频在线观看三级| 欧美二区三区的天堂| 国产精品一区免费在线观看| 成人免费一区二区三区视频 | 九九精品一区二区| 欧美韩国日本一区| 色悠悠久久综合| 另类专区欧美蜜桃臀第一页| 国产欧美精品国产国产专区 | 亚洲不卡一区二区三区| 久久午夜国产精品| 99精品视频在线免费观看| 人妖欧美一区二区| 国产精品乱码一区二区三区软件 | 91国产免费看| 狠狠狠色丁香婷婷综合激情| 成人欧美一区二区三区黑人麻豆 | 91精品国产免费| 成人免费视频caoporn| 丝袜美腿亚洲一区| 国产精品嫩草99a| 日韩一区和二区| 色天使色偷偷av一区二区| 久久91精品国产91久久小草| 亚洲一区二区三区自拍| 久久精品一区二区| 欧美肥胖老妇做爰| 99riav一区二区三区| 极品尤物av久久免费看| 亚洲一区免费观看| 国产精品毛片a∨一区二区三区| 日韩一区二区免费在线观看| 欧洲av一区二区嗯嗯嗯啊| 国产成人一区二区精品非洲| 日本成人超碰在线观看| 亚洲精品国产无天堂网2021| 欧美经典一区二区| 欧美一级在线观看| 99精品1区2区| 成人美女在线观看| 捆绑调教美女网站视频一区| 亚洲成a人v欧美综合天堂| 日韩一区有码在线| 国产精品福利一区二区| 国产亚洲精品bt天堂精选| 欧美一区二区三区视频免费 | 中文字幕免费观看一区| 精品国产自在久精品国产| 欧美电影一区二区三区| 欧美三日本三级三级在线播放| 99精品国产热久久91蜜凸| 99久久久精品| 成人精品视频一区二区三区尤物| 韩国视频一区二区| 精品无码三级在线观看视频| 久久99精品一区二区三区| 午夜婷婷国产麻豆精品| 亚洲第一狼人社区| 亚洲成人精品一区二区| 亚洲男人的天堂网| 亚洲男同性恋视频| 一区二区三区在线播| 亚洲精品美国一| 亚洲精品第1页| 亚洲欧洲制服丝袜| 国产精品久久久久婷婷二区次| 国产精品毛片大码女人| 中文字幕中文字幕中文字幕亚洲无线 | 国产精品一色哟哟哟| 国产福利一区在线观看| 国产福利精品一区二区| 顶级嫩模精品视频在线看| 成人黄色小视频| 9i看片成人免费高清| 色综合天天综合网天天看片| 一本久久a久久免费精品不卡| 成人精品在线视频观看| av不卡在线观看| 在线观看日韩精品| 欧美精品丝袜中出| 欧美变态tickle挠乳网站| 久久亚洲精品国产精品紫薇| 日本一区二区三区在线不卡| 欧美视频一区二区| 精品国产乱码久久久久久闺蜜| 亚洲欧美色一区| 国产精品一区二区你懂的| 宅男在线国产精品| 亚洲精品高清视频在线观看| 国产精品一区二区不卡| 欧美一区二区三区精品| 亚洲国产综合色| 波多野结衣中文字幕一区二区三区| 欧美一区二区视频网站| 一区二区三区欧美视频| 丁香婷婷综合激情五月色| 2020国产精品| 麻豆一区二区三区| 8x福利精品第一导航| 一区二区在线观看不卡| 欧美日韩国产成人在线免费| 亚洲情趣在线观看| 成人精品国产一区二区4080| 久久―日本道色综合久久| 久久99国产精品成人| 欧美一卡二卡三卡四卡| 石原莉奈一区二区三区在线观看| 色先锋aa成人| 亚洲欧美日韩国产综合| 99久精品国产| 综合久久久久久| 99久久久精品| 亚洲免费在线电影| 99国产精品久久久| 国产精品看片你懂得| 成人免费毛片app| 亚洲色图视频网站| 91影视在线播放| 亚洲日本韩国一区| 91美女片黄在线观看91美女| 自拍偷拍欧美激情| 色婷婷综合五月| 一区二区三区91| 欧美日韩黄色影视| 免费久久99精品国产| 日韩欧美久久一区| 激情综合五月天| 国产三级精品三级| 99r精品视频| 亚洲激情在线播放| 欧美中文字幕一区| 视频一区二区中文字幕| 欧美成人国产一区二区| 亚洲品质自拍视频| 久久精品国内一区二区三区| 欧美日韩国产精品成人| 亚洲二区视频在线| 91老师国产黑色丝袜在线| 国产嫩草影院久久久久| 国产一区二区三区综合| 亚洲精品一区二区在线观看| 国产资源精品在线观看| 欧美一级免费大片| 日韩国产精品久久| 69久久夜色精品国产69蝌蚪网|