| 网站首页 | 硬件维修 | 应用学院 | 网络组建 | 网站制作 | 菜鸟黑客 | 编程之道 | 数码大全 | 娱乐休闲 | 软件下载 | 在线视频 | 请您留言 | 技术论坛 | 
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
  • Alumin远程访问控制软件 让你…

  • 浏览器操作记录工具Internet…

  • Sleipnir 基于IE内核的绿色多…

  • 网页打不开 Windows的Hosts表…

  • windows IE浏览器精典技巧两…

  • 实现了!中文WinXP安装IE7 B…

  • 解决珊瑚虫QQ不能在Win2003运…

  • 在Win XP中让QQ跑得更快

  • Windows98注册表使用技巧27则

  • WINNT注册表使用技巧集锦

  • Q
    您现在的位置: 我是IT人 >> 应用学院 >> 操作系统 >> Linux >> 教程正文
    Linux,内核汉化大揭秘           
    Linux,内核汉化大揭秘
    作者:网络 文章来源:转载 点击数: 更新时间:2005-8-15
    [ 字体:缩小 正常 放大 | 双击自动滚屏 ]
    请选择合适的字体颜色:

    在阐述“基于Linux核心的汉字显示”的技术细节之前,有必要介绍一下原有Linux的工作机制。这里主要涉及到两部分的知识,这是Linux下终端和帧缓冲的实现。



    控制台(console)

    通常我们在Linux下看到的控制台(console)是由几个设备构成的。分别是/dev/ttyN(其中tty0就是/dev/console,tty1、tty2就是不同的虚拟终端(virtual console))。通常使用热键Alt+Fn来在这些虚拟终端之间进行切换。这些tty设备对应于linux/drivers/char/console.c和lvt.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.
    ”);

    }

    pputs函数向缺省输出文件(/dev/tty)发出“写”的系统调用write(2)。系统调用到Linux核心对应的核心函数->——console.c中的con_write( ), con_write( )最终会调用do_con_write(),在do_con_write()中负责把”hello,world.
    ”这个字符串放到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_srtuct结构中定义了?p> 用(或高层)tty的属性(例如宽度和高度等)。

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

    Static int do_write(struct

    Tty_struct * tty, int

    From_user,const unsigned char

    *buf, int conut)

    {

    struct vt_struct *vt = (struct

    vt_struct *)tty_>driver_data;

    //我们用到了driver_data变量

    …………

    currcons = vt->_num;

    //在这里的vc_nums就是1

    …………

    }

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

    “hello,world.
    ”中的每一个字符都要经过conv_uni_to_pc()这个函数转换成8位的显示字符。这样做的主要目的是使不同语言的国家能把16位的Unicode码映射到8位的显示字符集里,目前主要还是针对欧洲国家的语言,映射结果为8位,不包含双字节(double byte)的范围。

    这种从Unicode到显示字符的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的,所以我们有两种选择:

    1) 不进行conv_uni_to_pc()的转换

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

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

    经过conv_uni_to_pc()转换之后,”hello, world.
    ”中的字符被一个一个地填写到tty的缓冲区中,然后do_con_write()调用底层的驱动程序,把缓冲区中的内容输出到crt/Index.html'>显示器上(也就相当于把缓冲区的内容拷贝到VGA显存中去)

    sw->con putcs(vc_cons[currcons].d,

    (u16 *)draw_from, (u16 *)draw_to_

    (u16 *)draw_rwom, 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_d
    ta *conp,struct display *p, const unsignde short *s, int count, int YY, int xx )

    显示中文

    比如说我们试输出一句中文:putcs(你好
    ”)(“你好”的内码为0xc4.0xe3.0ba.0xc3)。这时候会怎么样呢?有一点可以肯定,“你好”肯定不会出现在屏幕上,原因是:

    1、核心中没有汉字字库,中文显示就是无米之炊了。

    2、在负责字符显示的void fbcon_cfb8_putcs()函数中,原有操作如下:

    对于每个要显示的字符,依次从虚拟终端缓冲区中以WORD为单位读取(低位字节是ASCII码,高8位是字符的属性)。由于汉字是双字节编码方式,所以这种操作是不可能显示出汉字的,只能显示出xxxx_putcs()输出的是一个一个的VGA字符。

    因此,要解决的问题:确保在调用do_con_write()时进行uni_pc转换不会改变原有编码,一个很直接的实现方式就是加载一个我们自己定制的Unicode映射表,loadunimap dirdct.uni,或者进接把direct.uni设置为核心的缺省映射表。

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

    首先需要在核心中加载汉字字库,然后修改fbcon_cfb8_putcs()函数,在fbcon_cfb8_putcs()中一次读两个WORD,检查这两个WORD的低位字节是否能拼成一个汉字,如果发现能拼成一个汉字,就算出这个汉字在汉字字库的的偏移,然后把它当成个16×16的VGA字符来显示。

    试验的结果表明:

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

    教程录入:小秦    责任编辑:小秦 
  • 上一篇教程:

  • 下一篇教程:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系站长 | 关于我们 | 友情链接 | 版权申明 |