用户管理  |   用户注册                                                                                    首 页软件下载教程中心办公指南flash动画文档下载办公公文

www.4oa.com - 中科软件园

投递文章 用户管理 投稿指南 资讯通告 :
站内搜索: 您的位置中科软件园 > 教程中心 > 操作系统 > Linux > 中文化 > 教程内容

基于Linux核心的汉字显示的尝试

2005-5-26 23:19:59  来源:本站整理  作者:不详 【 投递文章
内容提要:在阐述基于Linux核心的汉字显示的技术细节之前,有必要介绍一下原有linux的工作机制。这里主要涉及到两部分的知识,就是Linux下终端和帧缓冲的实现.控制台(console)通常我们在linux下...
在阐述基于Linux核心的汉字显示的技术细节之前,有必要介绍一下原有linux的工作机制。这里主要涉及到两部分的知识,就是Linux下终端和帧缓冲的实现.

控制台(console)

通常我们在linux下看到的控制台(console)是由几个设备完成的。分别是/dev/ttyN(其中tty0就是/dev/console,tty1,tty2就是不同的虚拟终端(virtual console)).通常使用热键alt+Fn来在这些虚拟终端之间进行切换。所有的这些tty设备都是由linux/drivers/char/console.c和vt.c对应。其中console.c负责绘制屏幕上的字符,vt.c负责管理不同的虚拟终端,并且负责提供console.c需要绘制的内容。Vt.c把不同虚拟终端下需要交给console.c绘制的内容放到不同的缓存中去。Vt.c管理着这样一个缓冲区的数组,并且负责在其间切换,以指定哪一个缓冲区是被激活的。你所看到的虚拟终端就对应着被激活的缓冲区。Console.c同时也负责接收终端的输入,然后把接收到的输入放到缓冲区。

帧缓冲(framebuffer)

Framebuffer是把显存抽象后的一种设备,可以通过这个设备的读写直接对显存进行操作。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。

Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。在使用帧缓冲时,Linux是将显卡置于图形模式下的.

试验

我们以一个简单的例子来说明字符显示的过程。我们假设是在虚拟终端1(/dev/tty1)下运行一个如下的简单程序。

main ( )

{

puts("hello, world.\n");

}

puts函数向缺省输出文件(/dev/tty1)发出写的系统调用write(2)。系统调用到linux核心里面对应的核心函数是console.c中的con_write(),con_write()最终会调用do_con_write( )。在do_con_write( )中负责把"hello, world.\n"这个字符串放到tty1对应的缓冲区中去。

do_con_write( )还负责处理控制字符和光标的位置。让我们来看一下do_con_write()这个函数的声明。

static int do_con_write(struct tty_struct * tty, int

from_user, const unsigned char *buf, int count) 其中tty是指向tty_struct结构的指针,这个结构里面存放着关于这个tty的所有信息(请参照linux/include/linux/tty.h)。Tty_struct结构中定义了通用(或高层)tty的属性(例如宽度和高度等)。

在do_con_write( )函数中用到了tty_struct结构中的driver_data变量。

driver_data是一个vt_struct指针。在vt_struct结构中包含这个tty的序列号(我们正使用tty1,所以这个序号为1)。Vt_struct结构中有一个vc结构的数组vc_cons,这个数组就是各虚拟终端的私有数据。

static int do_con_write(struct tty_struct * tty, int

from_user,const unsigned char *buf, int count)

{

struct vt_struct *vt = (struct vt_struct *)tty->

driver_data;//我们用到了driver_data变量

. . . . .

currcons = vt->vc_num; file://我们在这里的vc_nums就是1

. . . . .

}

要访问虚拟终端的私有数据,需使用vc_cons〔currcons〕.d指针。这个指针指向的结构含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大小等等。

"hello, world.\n"中的每一个字符都要经过conv_uni_to_pc( )

这个函数转换成8位的显示字符。这要做的主要目的是使不同语言的国家能把16位的UniCode码映射到8位的显示字符集上,目前还是主要针对欧洲国家的语言,映射结果为8位,不包含对双字节(double byte)的范围。

这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的。所以我们有两个选择∶

1不进行conv_uni_to_pc( )的转换。

2加载符合双字节处理的映射关系,即对非控制字符进行1对1的不变映射。我们自己定制的符合这种映射关系的UNICODE码表是direct.uni。

要想查看/装载当前系统的unicode映射表,可使外部命令loadunimap。

经过conv_uni_to_pc( )转换之后,"hello, world.\n"中的字符被一个一个地填写到tty1的缓冲区中。然后do_con_write( )调用下层的驱动,把缓冲区中的内容输出到显示器上(也就相当于把缓冲区的内容拷贝到VGA显存中去)。

sw->con_putcs(vc_cons〔currcons〕.d, (u16 *)draw_from, (u16

*)draw_to-(u16 *)draw_from, y, draw_x);

之所以要调用底层驱动,是因为存在不同的显示设备,其对应VGA显存的存取方式也不一样。

上面的Sw->con_putcs( )就会调用到fbcon.c中的fbcon_putcs()函数(con_putcs是一个函数的指针,在Framebuffer模式下指向fbcon_putcs()函数)。也就是说在do_con_write( )函数中是直接调用了fbcon_putcs()函数来进行字符的绘制。比如说在256色模式下,真正负责输出的函数是void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,const unsigned short *s, int count, int

yy, int xx)

显示中文

比如说我们试图输出一句中文∶putcs(你好\n );(你好的内码为0xc4,0xe3,0xba,0xc3)。这时候会怎么样呢,有一点可以肯定,"你好"肯定不会出现在屏幕上,原因有∶核心中没有汉字字库,中文显示就是无米之炊了.

1在负责字符显示的void fbcon_cfb8_putcs( )函数中,原有操作如下∶对于每个要显示的字符,依次从虚拟终端缓冲区中以WORD为单位读取(低位字节是ASCII码,高8位是字符的属性),由于汉字是双字节编码方式,所以这种操作是不可能显示出汉字的,只能显示出xxxx_putcs()是一个一个VGA字符.

要解决的问题∶

确保在do_con_write( )时uni□pc转换不会改变原有编码。一个很直接的实现方式就是加载一个我们自己定制的UNICODE映射表,loadunimapdirect.uni,或者直接把direct.uni置为核心的缺省映射表。

针对如上问题,我们要做的第一个尝试方案是如下。

首先需要在核心中加载汉字字库,然后修改fbcon_cfb8_putcs()函数,在fbcon_cfb8_putcs( )中一次读两个WORD,检查这两个WO

[1] [2] [3]  下一页

(评论内容只代表网友观点,与本站立场无关!)[ 全部评论 ]

网友评论:

    用户名:

    评   分:100分 85分 70分 55分 40分 25分 10分 0分

    内 容:

                 (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码

关于本站 - 网站帮助 - 广告合作 - 下载声明 - 友情连接 - 网站地图 -有事点这里