首页 做一个支持图形界面的操作系统(下)

做一个支持图形界面的操作系统(下)

举报
开通vip

做一个支持图形界面的操作系统(下) 让你自己的操作系统支持鼠标 副标题:做一个支持图形界面的操作系统(下) 作者:谢煜波 文章来源:本站原创 点击数: 240 更新时间:2004-10-7 pdf 格式:http://purec.binghua.com/Soft/Class9/Class16/200410/67.html 源代码:http://purec.binghua.com/Soft/Class9/Class16/200410/66.html 转载请注明原作者及出处 让你自己的操作系统支持鼠标 ——做一个...

做一个支持图形界面的操作系统(下)
让你自己的操作系统支持鼠标 副标题:做一个支持图形界面的操作系统(下) 作者:谢煜波 文章来源:本站原创 点击数: 240 更新时间:2004-10-7 pdf 格式:http://purec.binghua.com/Soft/Class9/Class16/200410/67.html 源代码:http://purec.binghua.com/Soft/Class9/Class16/200410/66.html 转载请注明原作者及出处 让你自己的操作系统支持鼠标 ——做一个支持图形界面的操作系统(下) Version 0.01 ( 对应 pyos 版本 2004_10_06_15_00 ) 哈尔滨工业大学 谢煜波 ( email:xieyubo@126.com 网址:http://purec.binghua.com ) ( QQ:13916830 哈工大紫丁香 BBS ID:iamxiaohan ) 前言 在上篇中,我们已经了解了怎样显示一个图形界面,包括怎样操作显卡,怎样显示图片,怎样显示中 文汉字及英文字符。然而,作为一个完整的图形界面,不光需要显示信息,还需要接受用户输入,而在图 形界面中,最重要的输入手段就是通过鼠标进行输入,在这一篇中我们将描述一下怎么样让你自己的操作 系统支持鼠标。 由于鼠标存在很多的接口 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ,这里我们只对最常用的 PS/2 协议进行描述。本文主旨在于引导对此 感兴趣而又不知怎么下手的朋友,亲自动手进行实验,因此,不会详细描述协议的完整内容,如果你需要 了解整个协议内容,你应当去寻找相关文献进行阅读,也可以参考一个本文的参考文献。 本文所描述的内容均基于我自己对此问题的理解,其中定然存在偏差及不当之处,因此,千万别将此 文中所描述的内容作为“ 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 ”,如果你一旦发现其中存在的问题,非常欢迎您及时与我联系,我也会在 纯 C 论坛上(http://purec.binghua.com)及时对其中出现的问题进行反馈。 本次我同样将以 pyos 为基础进行实验,下面我们先来看看这次实验的最终成果: 这是 pyos 启动后,等待用户登陆的界面 这是用户登陆后的界面,相当于 windows 的桌面 用鼠标的右键可以拖动应用程序图标 单击图标可以打开应用程序,这个应用程序是一个推箱子游戏 用 I,J,K,L 四个键可以玩游戏,Esc 键或者用鼠标单击窗口标题栏的关闭按钮可以关闭它 用鼠标右键拖动窗口的标题栏可以拖动整个窗口,就像 windows 中一样 单击左下角的“关机”按钮,可以退出 pyos 这是关机后,pyos 退出后的界面 上面就是本实验的最终实验结果,希望通过阅读此篇实验 报告 软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载 之后,你能完成一个比这更好的实验:)。 本次实验对也是对前几次实验的一个综合,其中用到了《操作系统引导探究》、《保护模式下的 825 9A 芯片编程及中断处理探究(上下)》、《编写操作系统之键盘交互的实现》、《做一个支持图形界面的操 作系统(上)》这几篇实验报告中所描述的内容。因此,如果你想更好的理解本实验的内容,可以在纯 C 论坛上找到上面几篇实验报告进行参考,本篇实验报告将不会对以前实验报告中已提到的内容重复论述。 本次实验,得到了不少朋友的帮助,其中,哈尔滨工业大学紫丁香网友 SwordLea 建议 支持符合 windows 标准的 bmp 图片格式,pineapple 帮助我找了到了 windows 下的图标,ho tice 指导使用 PhotoShop, and so on~~:) 言归正传,下面开始进行我们的实验。 一、通过对 i8042 键盘控制器编程控制鼠标 现在我们用的鼠标,大多是支持 PS/2 协议的鼠标,这样的鼠标也被称为 PS/2 鼠标,PS/2 协议其实支 持两种设备,一种是键盘,一种是鼠标,它是由 IBM 公司制定的,协议的本身定义了键盘与鼠标同主机进 行通迅的规则,其中包括了大量的物理及电器方面的信息,比如鼠标连接线的插头的管脚(针)数,每个 管脚(针)的用途,电平是多少等,不过幸运的是,我们并不需要对这样的硬件细节有详细的了解,就可 以完成我们的操作系统,我们需要了解的就是怎样初始化鼠标,以及怎样从鼠标中获得信息。 这里,我们首先来看看怎样初始化鼠标。根据 PS/2 协议,鼠标是由键盘的控制器(i8042)进行控制的, 键盘控制器(i8042)总共有两个通道,一个通道由键盘使用,另一个通道由鼠标使用,我们对鼠标进行操 作也是通过 i8042 芯片来完成的,因此,现在的重点就是了解并熟悉怎样对 i8042 进行编程,来完成对鼠标 的控制。 i8042 支持两种工作模式——AT 模式及 PS/2 模式,这都是由 IBM 所定义的一些规范,i8042 在计算 机启动时会自动检测用户是否使用的支持 PS/2 协议的键盘及鼠标,以决定是否工作在 PS/2 模式下,现在 我们假设我们使用的都是 PS/2 键盘及鼠标,因此,现在 i8042 工作在 PS/2 模式下(请记住这一点,即 i80 42 可以工作在 AT 模式或者 PS/2 模式下,并且现在假设其工作在 PS/2 模式下,这在后面将会用到)。 与 i8042 有关的 I/O 端口共有两个,一个是 0x60 端口,一个是 0x64 端口,如果我们想获得 i8042 的 状态,我们需要读 0x64 端口,这将返回 i8042 中状态寄存器的内容。如果我们想向 i8042 发送命令,我们 需要先把命令发送到 0x64 端口,然后紧接着把这个命令的参数发送到 0x60 端口,然后我们可以通过读 0x 60 端口,获得 i8042 返回给我们的数据。 下面我们就来看看,应当发送什么样的命令去控制鼠标,这涉及到下面几个需要发送给 i8042 的命令: 0xA8 命令:许可 i8042 的鼠标通道,即允许鼠标操作。 0xD4 命令:把发往 0x60 端口的参数数据发给鼠标。 0x60 命令:把发往 0x60 端口的参数数据写入 i8042 的控制寄存器。 从上面的 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 我们可以基本窥见怎样操作鼠标。首先,我们应向 i8042 的 0x64 端口发送 0xA8 命令, 以许可 i8042 的鼠标通道,以便完成对鼠标的操作。其次我们应向 i8042 的 0x64 端口发送 0xD4 命令,以 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 i8042 我们需要控制鼠标,并把控制鼠标的命令发到 i8042 的 0x60 端口,再从 i8042 的 0x60 端口取回 鼠标发给我们的数据,这一过程无疑是比较简单的,我们先来看看,我们应向鼠标发送什么样的控制命令, 然后再看看实际的代码。 控制鼠标的命令非常之多,比如 0xFF 命令可以让鼠标复位;0xFE 命令可以让鼠标重新发送上次的数 据包;0xF3 命令可以设置鼠标的采样率,也即鼠标滑动时的灵敏度;0xF4 命令可以允许鼠标向主机发送数 据包等。这里最重要的就是 0xF4 命令,而其它的设置鼠标的命令我们暂时可以不用理会,因为使用默认值 已经能很好的完成本实验了。要理解 0xF4 命令有什么作用,我们需要先了解一下鼠标的四种工作模式:R eset 模式,Stream 模式,Remote 模式及 Wrap 模式。 首先是 Reset 模式,当鼠标初次加电或收到 0xFF 命令之后,鼠标就处于此模式,然后鼠标将进行一 系列的初始化及检测工作,包括设定默认的采样率等,完成初始化极检测之后,鼠标将进入 Stream 模式。 在 Stream 模式下,如果鼠标被移动,或者有键被按下,那么鼠标将向主机发送数据包,并提请一个 中断请求,主机需要响应此中断,并在中断处理程序中取得鼠标发送的数据包。如果在 Stream 模式下,我 们向鼠标发送 0xF0 命令,将使鼠标进入 Remote 模式。 Remote 模式同 Stream 模式差不多,主要工作就是检测鼠标是否被移动及是否有键被按下,不过它与 Stream 模式的区别在于,它并不会主动的向主机提请中断请求,也即它不会主动的向主机发送数据包,而 是被动的等待主机使用 0xEB(读数据命令)后,再向主机提请中断请求,发送数据包。换句话说,如果在 R emote 模式下,你每次欲读数据时,均需要向鼠标发送 0xEB 命令,而如果是在 Stream 模式下,鼠标会自 动向你发送数据。 Wrap 模式主要用于检测鼠标与主机之间的连线是否正常,主机向它发送命令,它一般不会执行此命 令,而只是简单的将此命令原封不同的回送给主机,主机可比较它发出的命令及接收到的命令是否一致, 并以此来认定鼠标与主机之间的连线是否正常。 从上面的描述中我们可以看出,我们需要关心的只有 Reset 模式及 Stream 模式,但对于操作系统编写 人员而非 BIOS 编写人员来说,真正需要关心的只有 Stream 模式,这是因为当计算机启动的时候,BIOS 会自动检测鼠标,与鼠标进行通信,这个时候它会向鼠标发送 0xFF(复位)命令,然后鼠标会自检,并通 知主机自检是否正常,然后鼠标就将处于 Stream 模式,此时,鼠标已经开始检测鼠标是否移动及是否有键 按下了,但是它不会立即就向主机发送数据,因为有可能主机还没有进入真正的操作系统,主机还正在启 动中,因此,鼠标会等待主机的通知,直到主机给它发送 0xF4 命令后,它才开始向主机发送数据。 所以,在操作系统中初始化鼠标的动作就很简单了,请看下面 pyos 中初始化鼠标的相关代码: // 许可 鼠标 void mouse_enable_mouse() { // 对 8042 键盘控制芯片进行编程 // 允许 鼠标 接口 io_write_to_io_port( 0x64 , 0xa8 ) ; // 通知 8042 下个字节的发向 0x60 的数据将发给 鼠标 io_write_to_io_port( 0x64 , 0xd4 ) ; // 允许 鼠标 发数据 io_write_to_io_port( 0x60 , 0xf4 ) ; // 通知 8042,下个字节的发向 0x60 的数据应放向 8042 的命令寄存器 io_write_to_io_port( 0x64 , 0x60 ) ; // 许可键盘及 鼠标 接口及中断 io_write_to_io_port( 0x60 , 0x47 ) ; } 有了上面的描述,这段代码就相当简单了,首先它向 i8042的 0x64端口发送了一个 0xA8 命令,通知 i8042,允许鼠标通道。然后,它向 i8042的 0x64端口发送了一个 0xD4命令,这个命令表示,下面发给 0 x60的命令需要发给鼠标,所以,紧接着,它向 i8042的 0x60端口,也即向鼠标,发送了 0xF4命令,这 个命令将允许经过 BIOS初始化后,现在已处于 Stream模式下的鼠标给主机发送数据包。随后,它向 i804 2的 0x64端口发送了 0x60 命令,表示,下面发向 0x60端口的数据需要写入 i8042的控制寄存器,最后它 向 i8042的 0x60端口发送了值为 0x47的数据,这个数据被写入了 i8042的控制寄存器。下面,我们就来 看看这个控制寄存器,以明白,这里为什么需要向它发送这样一个值为 0x47的数据。 下面就是 i8042的控制寄存器的格式,这个控制寄存器总共有 8位,即 1个字节。 位 0:键盘中断标志位,如果置 1,那么如果有键盘动作,则 i8042将提请 IRQ1中断。 位 1:鼠标中断标志位,如果置 1,那么如果有鼠标动作,则 i8042将提请 IRQ12中断(在 AT模式下 这位不使用,只在 PS/2模式下有效。这里可以回忆一下前面我们提到的 i8042可以工作在 AT或者 PS/2两 种模式下的描述)。 位 2:系统标志位,上电的时候是 0,自检成功后是 1。 位 3:键盘锁标志位,如果是 1,将忽略键盘锁,这主要是为了兼容一些老式的带锁的键盘,而且这 位只在 AT模式下使用,PS/2 模式下将不使用此位。 位 4:键盘接口标志位,如果置 1,将禁止使用键盘接口。 位 5:在 AT模式下,这是 AT键盘协议位。置 0的时候,i8042将使用 AT协议,如果置 1,将使用 XT 协议。在 PS/2模式下,这是鼠标接口(通道)标志位,如果置 1将禁止鼠标接口(通道)。 位 6:键盘扫描码转换标志位。如果置 1 将把真实的键盘扫描码转换为第一套键盘扫描码(有关此内 容详见《编写操作系统之键盘交互的实现》一文)。 位 7:保留,应置为 0。 二、鼠标数据包简析 在上节中,我们知道了怎样对 i8042 进行编程,以完成对鼠标的初始化操作,那么当鼠标的初始化完 成之后,如果有鼠标动作发生,比如用户移动了一下鼠标,或者按下了鼠标键,那么鼠标将把数据包发回 给主机,现在我们就来看看鼠标发回给主机的数据包的结构,在了解这个结构之前,我们先要知道现存的 总共有两类鼠标,一类就是所谓的 2D(二维)鼠标,它就是我们平常用的那种没有滚轮的鼠标,由于这种 鼠标在位移上只有 X 与 Y 两个方向,所以称之为 2D(二维)鼠标;还有一类就是现在比较常见的 3D(三 维)鼠标,它们中间存在有一个滚轮,而这个滚轮会产生一个额外的 Z 位移量,因此,它在位移上有 X、 Y、Z 三个方向,所以又称之为 3D(三维)鼠标。下面,我们就来看看这两类鼠标发给主机的数据包有什 么不同。下面,我们先来看看二维鼠标。 位 0:左键按下标志位,为 1 表示左键被按下。 位 1:右键按下标志位,为 1 表示右键被按下。 位 2:中键按下标志位,为 1 表示中键被按下。 位 3:保留位,总是为 1。 位 4:X 符号标志位,为 1 表示 X 位移量为负。 位 5:Y 符号标志位,为 1 表示 Y 位移量为负。 位 6:X 溢出标志位,为 1 表示 X 位移量溢出了。 位 7:Y 溢出标下位,为 1 表示 Y 位移量溢出了。 下面,我们再来看看三维鼠标的数据包结构。 三维鼠标数据包中第一个数据包每位的含义与二维鼠标数据包中第一个数据包中每位含义完全相同, 唯一不同的就在于它每次会多发送一个数据包,即第 4 个数据包,这个数据包包含了 Z 的位移量,同 X、 Y 位移量相同的是,它们都是以补码表示的。不过与 X 及 Y 位移量不同的是,Z 位移量是 4 位的,其中最 高位(第四位)是符号位,因此,Z 位移量的有效的范围为:-8~7。而 X 与 Y 的位移量是 9 位的,最高一 位(第 9 位)是符号位,这个符号位在第一个数据包中表示,故,X 与 Y 的位移量的有效范围为:-256~2 55。 看到这里,你或许有疑问了,系统是怎么来知道到我到底应当接收 3 个数据包还是接收 4 个数据包的 呢?三维鼠标的标准是由微软制定的,最初,这种三维的鼠标只工作在标准的 PS/2 模式下,如果你想让它 工作在三维模式下,你需要用 0xF3 这个设置鼠标采样率的命令,按如下的顺序进行操作: 1. 设置鼠标采样率为 200 2. 设置鼠标采样率为 100 3. 设置鼠标采样率为 80 这之后,如果你的鼠标是个三维鼠标,那么,它将转到三维模式下进行工作,这个时候,主机向它发送 0xF2(获得鼠标类型 ID)命令,你的工作在三维模式下的鼠标将向主机返回它的类型 ID,但如果你的鼠 标不支持三维模式,即如果你的鼠标只是一个二维鼠标,它返回给主机的类型 ID 将是 0,这样,主机就能 够知道现在你用的鼠标是什么类型的鼠标,并由此知道应当接受 3 个还是 4 个数据包了。本实验将只操作 标准的二维鼠标,如果你有兴趣,你可以对程序进行改动,以让它支持三维鼠标。 现在,我们来看看,这个数据包是怎么被主机获得的。在《保护模式下的 8259A 芯片编程及中断处理 探究(上下)》这篇实验报告中我们知道了,鼠标中断是通过 IRQ12 提出的,因此,在操作系统中,我们需 要为 IRQ12 这号中断编写一个中断处理程序,然后在这个中断处理程序中读取鼠标发来的数据包,下面, 就让我们来看一看这段存在于 pyos 中的真实的代码: // 鼠标 中断处理函数 void mouse_handle_for_mouse_interrupt() { static int x_position = 444 ; // 定义 鼠标 的初始 x 坐标 static int y_position = 300 ; // 定义 鼠标 的初始 y 坐标 static int count = 0 ; // 此变量用来记录这是第几个数据包了 // 因为 鼠标 发来的每个数据包 // 都会引起一个中断 static int x_sign = 0 ; // 用来表示 x 位移量的符号 static int y_sign = 0 ; // 用来表示 y 位移量的符号 static struct message_message_struct message ; // 定义一个消息 // 这个消息用来通知操作系统内核有鼠标动作 char ch = io_read_from_io_port( 0x60 ) ; // 通过 0x60 端口,获得 鼠标 发来的数据包 switch( ++count ){ // 检测是第几个数据包 case 1 : // 收到的是第一字节 // 检测按键信息 message.dose_left_button_down = ch & 0x1 ; message.dose_right_button_down = ch & 0x2 ; // 获得 x 及 y 位移量的符号 x_sign = ch & 0x10 ? 0xffffff00 : 0 ; y_sign = ch & 0x20 ? 0xffffff00 : 0 ; break ; case 2 : // 收到的是第二字节,即 x 的位移量 x_position += ( x_sign | ch ) ; // 计算新的 x 坐标 break ; case 3 : // 收到的是第三字节,即 y 的位移量 y_position += -( y_sign | ch ) ; // 计算新的 y 坐标 // 把消息发送给内核 message.message_type = MESSAGE_MOUSE_MESSAGE ; // 设定消息的类型 message.x_position = x_position ; // 设定消息的参数(x 的坐标) message.y_position = y_position ; // 设定消息的参数(y 的坐标) message_put_message( &kernel_message_queue , message ) ; // 把消息放进内核的消息队列中 count = 0 ; // 三个数据包已接收完毕,故清零计数器 break ; } } 上面的代码注释已经很详细了,有关“消息”这部份,如果你已前看过《编写操作系统之键盘交互的 实现》这篇实验报告,应当对它非常熟悉,如果你没有看过,那么也别着急,在后面分析整个 pyos 实验程 序架构的时候,还会对它进行描述。 这次的 pyos 实验,支持了 Windows 标准的 BMP 图片格式,下面我们就来描述一下对这个标准 BMP 图片格式的处理问题,以便于更好的理解本实验。 三、Pyos所支持的 Windows标准的 BMP图片格式 BMP 图片格式其实不是只单单的一种格式,而是一类格式的总称,这包括皆如 24 位真彩格式,16 位 真彩格式,16 位真彩格式中又有 555 格式,565 格式等,还有 4 位,8 位调色板格式,压缩存储格式等, 非常复杂,本次 Pyos 只支持了其中的一种,即非压缩的,16 位真彩色 555 格式,这也是现在的 32 位 win dows 默认的 16 位 BMP 格式。由于 BMP 格式的纷繁复杂,我想有关这方面最权威最全面的资料莫过于通 过 MSDN 获得了,因此,本实验报告并不打算对此进行完整而详尽的描述,本实验报告将只描述本实验所 用到的一些细节,以便于你能非常便利的阅读本实验的代码。 下面我们来简单理解一下 BMP 格式。BMP 格式又称之为位图格式,它是把一幅图的色彩信息完整的 记录了下来,每个点都用一个色彩于表示,这样在显示的时候,只需要读取此文件,然后获得每个点的色 彩数据,然后把这个点用这个色彩显示到屏幕上就行了,由于每幅图都是由一个一个的点构成的,因此, 把所有的点都显示完了之后,就完成了整幅图片的显示。 但是,一个文件光记录每个点的色彩信息还不行,还需要记录这个图片的大小,以及这幅图片每个点 用几个数据位来记录色彩等信息,这部份信息被称之为 BMP 文件的头信息,而被记录在文件的开头位置。 下面我们就来看看这个文件头: struct bmp_bmp_head_struct{ short type ; // 类型 int size_file ; // 大小 short reserved_0 ; short reserved_1 ; int offset ; // 位图阵列的起始位置 struct bmp_bmp_info_head_struct info_head ; } ; 这个结构比较简单,首先是 2 字节的类型数据,用来认定这是不是一个 BMP 文件,紧接着是一个 4 字节的数据,用来表示这个文件的大小,跟着的 4 字节保留给将来使用,随后的 4 字节是一个偏移量,这 个偏移量指出了每个点的色彩数据在这个 BMP 文件中的什么位置,这对我们来说非常重要。随后,是一个 所谓的 BMP 信息结构,下面我们就来看看这个所谓的 BMP 信息结构中到底都有些什么数据值得我们关心。 struct bmp_bmp_info_head_struct{ int the_struct_size ; int width ; int height ; // 下面还有数据,但目前 pyos 只处理 16 位真彩位图,因此下面的数据不要了 } ; 这个结构也比较简章,首先是 4字节的数据,用来表示这个结构的大小,随后的 4字节数据给出了这 个文件所描述的图片的宽度,紧接着的 4个字节给出了这副图片的高度,随后还有一些数据,它们给出了 这个图片是否使用了压缩格式来存放数据,每个点是用多少位来表示的,以及是否使用了调色版,如果使 用了调色版,后面还有调色版的数据。由于本篇只处理 16 位的真彩位图,所以下面的数据本实验都不考 虑了,但是,如果你想做一个更好更完善的系统,那么你需要好好的研究一下 BMP完整的格式,然后根据 其中所记录的不同信息,在程序中进行不同的处理,pyos 只是一个原理性的实验系统,故而,并不打算在 此方面多下功夫,非常希望能在以后见到改进版本:P。 有了上面的描述,我们可以对怎么样显示图片有个比较良好的认识了,我们现在来看看 pyos中的实 际的处理代码: // 显示 pbmp 格式的图片 void vesa_show_bmp_picture( unsigned int x , unsigned int y , void *bmp_addr , unsigned shor t mask_color , int dose_use_mask_color ) { // 这里只支持 windows 标准 16 位 bmp 格式图片,(1:5:5:5) struct bmp_bmp_head_struct *bmp_head = ( struct bmp_bmp_head_struct * )bmp_addr ; int width = bmp_head->info_head.width ; // 获得图片的宽度 int height = bmp_head->info_head.height ; // 获得图片的高度 // 下面记算存储每个点的色彩的信息所在的位置 unsigned short *color = ( unsigned short * )( ( unsigned int )bmp_addr + bmp_head->offset ) ; // 由于一行的字节数比须是 4 的倍数,因此,这里先计算每行需要的填充数,除 2 是因为每个像素两 个字节 int fill_length = width * 2 % 4 / 2 ; // bmp 的存放顺序是从下到上,从左到右 for( int i = height - 1 ; i >= 0 ; --i ){ for( int j = 0 ; j < width ; ++j ){ // 取得每个点的色彩信息 // 由于 windows 默认的是 555 格式,而 pyos 用的是 565 格式,因此先进行一下转换 unsigned short temp_color = vesa_change_color_form_555_to_565( *color ) ; if( !dose_use_mask_color || temp_color != mask_color ){ // 画出每个点 vesa_draw_point( x + j , y + i , temp_color ) ; } ++color ; } // 填充 color += fill_length ; } } 上面的代码也是比较简单的,而且有较为详尽的注释,这里就不多描述了,需要提醒的只有两点:第 一,BMP 文件存放图片的默认顺序是从一幅图的最左下角开始,从左到右,从下到上,而不是按正常的从 上到下的顺序。而且,每存一行数据,都要检测一下是否是 4 的倍数,如果不是,则填充 0,以使它总是 4 字节的倍数,这也称之为 4 字节对齐。 第二个需要注意的地方就是,windows 默认使用的 16 位真彩位图是 555 格式,也就是说红(R)、绿 (G)、兰(B)都用 5 位数据来表示,而 pyos 现在用的是 565 格式(即红(R)用 5 位表示,绿(G)用 6 位表示,兰(B)用 5 位表示),因此,在显示之前,需要将其转换一下,具体的内容,可以参看源代码。 四、pyos系统架构 本实验所需的基础知识,前面已经全部描述完了,这里我们就来看看 pyos 的主程序架构。首先需要 说明的是,由于目前 pyos 还没有完成磁盘驱动及文件系统,因此,pyos 中所用到的所有资源,包括图片、 字库等,都是在最初制作 pyos 的启动映象(pyos.img)的时候,被一个称之为“make_together.exe”的程序 直接写到磁盘上的固定地址的,然后,再由 setup.asm 在系统引导时,读入内存中的固定位置,而操作系统 内核在使用它们时,也是通过这个内存的固定地址使用的。了解这一点,对看源代码非常有帮助。 当 setup.asm 读入了所用的图片、字库等资源后,系统将跳到 kernel.c 处执行,这是系统的内核,我们 现在来看看这个文件中的一些程序: // 内核主函数 void kernel_main() { // 操作系统初始化 system_init() ; old_picture = ( unsigned short * )0x100000 ; // 越过前面的只读内存区 // 画登陆界面 kernel_draw_login_form() ; // 0x903b3 // 清空键盘缓冲区 io_read_from_io_port( 0x60 ) ; // 初始化消息队列 message_init_message_queue( &kernel_message_queue ) ; // 开中断 interrupt_open_interrupt() ; struct message_message_struct message ; kernel_kernel_state = KERNEL_WAIT_USER_LOGIN ; // 进入消息循环 for( ;; ){ if( !message_get_message( &kernel_message_queue , &message ) ){ continue ; } if( message.message_type == MESSAGE_SHUTDOWN_COMPUTER ){ break ; } switch( message.message_type ){ case MESSAGE_KEYBOARD_MESSAGE : // 处理键盘消息 „„ case MESSAGE_MOUSE_MESSAGE : // 处理 鼠标 消息 „„ } } // 停机 for( ;; ){ __asm__( "hlt" ) ; } } 这段程序也是非常简单的,首先调用 system_init()来进行一些初始化操作,比如初始化中断向量表、 初始化键盘、初始化鼠标等,然后,它调用 kernel_draw_login_form()这个函数来显示等待用户登陆的界 面,最后它初始化了一个消息队列,然后进入一个消息循环,不断的从这个消息队列中取出消息,并根据 消息的类型进行不同的处理。每当有键盘动作或鼠标动作的时候,键盘与鼠标的中断处理程序都会构造一 条消息,然后把这条消息放到内核的消息队列中,这样内核就能知道用户进行了什么操作,然后根据用户 操作进行处理。比如,如果鼠标消息中指示出用户按下了鼠标左键,那么内核将检测用户的鼠标是否处在 应用程序图标所在的范围内,如果是,则启动应用程序(这在实验中就是那个推箱子游戏)。如果你有在 windows下编写 windows应用程序的经验,对此应当是比较好理解的。具体的细节可以参看源程序。另外, 有关消息队列,中断处理,这部份内容在《编写操作系统之键盘交互的实现》有很详尽的描述,这里就不 多费时间了。 /* 系统初始化 */ void system_init() { // 由于以后可能向 gdt 表中增添项目,因此,此处应重新初始化 gdt 表,以保存 gdt 表位置 system_init_gdt() ; // 初始化中断 interrupt_init() ; // 初始化键盘 keyboard_init() ; // 初始化 鼠标 mouse_init() ; } 上面一段代码,就是系统初始化的程序,它在 kernel.c 的 main()函数中被内核调用,以完成系统的 一些初始化操作,具体的代码,可以参看源程序。 注:pyos源代码中,每个函数或变量的第一个单词都表明了这个函数存在于哪一个文件中,比如:sy stem_init()中第一个单词 system表明了这个函数存在于 system.c这个文件中,希望这种命名方式能有助 于你阅读源程序。 五、进一步实验的建议 由于 pyos 或许是更多的着眼于原理性或说基础性,因此它在很多方面做了一些假定及忽略。比如, 在本实验中,它没有检测用户是否使用了三维鼠标,因此,没有对三维鼠标提供支持,它也没检测用户使 用的到底是不是 555 格式的真彩 BMP 图片文件,而假定用户就是使用的这种图片,也没有对这种图片文件 是否有错误进行任何的差错检验与校正。另外,它采用了一种最蜗牛的方式,它的每幅图,每条线,都是 一个点一个点画上去的,图形拷贝也是一个点一个点的赋值,因此,pyos 运行起来非常的慢,而实际的系 统是绝不会像这样的。你可以针对它进行一系列的优化。比如在拷贝图片时用 memcpy 一块内存一块内存 的拷贝或者在内存中先建一个缓冲区,在缓冲区中把图都画好了,再一次性的使用 memcpy 拷贝到显卡的 内存中进行显示。知道了基本原理,怎样优化应当并不是一件高不可及的事。 另外,如果你想对本文中所泛泛描述的东东的细节有较深入的了解,可以阅读本文的参考文献,它们 中的绝大部分都能在纯 C 论坛上找到。 后记 本文是《做一个支持图形界面的操作系统》的下篇,上篇在纯 C 论坛上贴出之后,收到了不收朋友的 反馈意见,大家都对是否应当完成一个图形化的操作系统,或者 pyos 是否应当走图形化的道路,提出了自 己非常宝贵的意见,在这里对各位朋友表示由衷的感谢,也想就此机会,谈谈自己对此问题的看法。 首先,从 pyos 的角度来说,pyos 只是一个实验性的操作系统,目的是用来验证所学,因此,pyos 追 求的是从一种一无所有的原始状态开始建造,力图通过这样一个过程了解较为详细的实现细节,所以,py os 简单、慢,但力图完整。并不打算成为一个真正可以实用并被使用的 os,在 pyos 中,只是验证可以做 到,但并不是在实际的 os 中,一定要做到。pyos 是一个起步,而不会是最终的结果。在本实验中,pyos 刻意的去模拟了 windows 的图形界面,原因只在于,想通过这样的模拟,能些许的揭开长期以来披在 wind ows 或其它操作系统上神秘的面纱,让对此不了解的人,能认识到:只要一步一步的做下去,并不是只有 微软,而我们也有可能做到。从而,让更多的人有信心也有这个兴趣来编写属于自己的操作系统。 我总是力度将一个完整的 os,切分成若干细节,而每次实验,都用 pyos 去实现一个细节,而忽略掉 其它的细节,因此,每次实验的 pyos 的架构都不一样,变化非常大,有时甚至没有多少共通之处,然而, 我总认为只要把每个细节都了解清楚了,每个细节我们都可以自己实现了,那么,希望有一天,我们可以 将这若干个细节组合起来,像这次的这个图形界面其实就是前面绝大部份实验综合的结果。 其次,从一般意义上讲,如果你打算开发一个 os,是否开发图形界面,我的观点是:如果你是为一个 特定的目标开发,那么你需要跟据你的目标进行选择,你是要开发一个高效的系统,还是一个界面更友好 的系统。如果需求不同,我想这结论也应当是不同的,像 pyos,定义为一个中文操作系统,要支持中文, 图形模式就是必须的了。 如果你是为学习一种技能或知识,那么我建议你可以尝识一下图形界面的开发,它要考虑的问题会比 字符界面更复杂,而且更难处理,这样的一种挑战显然是有益的。 其实,不论你决定是否选用图形界面,最关键的一点是你有兴趣去这样做。为完成这个实验,我三天 总共只睡了不到 15 个小时,四顿没吃饭,逃了三天整整十节大课(幸好老师没点我名,thank good ness~ ~:P,当然,也并不是非要这样,不过一般说来,写上程序了,一般是很难中途停手的),这一切只有一个 支撑,就是兴趣。所以,如果你要决定使用图形界面,或者不使用图形界面,请先确认你对它有足够的兴 趣,that's your own os, just as you like! Pyos 是一个开放的系统,你可以在纯 C 论坛上找到它从创生以来的所有资料,包括所有的实验报告 及所有的源代码,所有的相关资源。Pyos 没有基于任何现有操作系统,它只是一些原理的实现,因此,Py os 不遵守 GPL 公约,它也不要求对 Pyos 进行修改的朋友遵守 GPL 公约,不过,我非常希望,如果你也在 进行类似的开发或者实验,你也能在可能的情况下,公开你的心得,你的体会,让更多的朋友了解你的工 作,也让更多的朋友能从中获得益处。学术需要的是交流,中国古代春秋战国时期的百家争鸣,导致了许 多古代杰出思想家的出现,你有一个苹果,我有一个苹果,我们交换之后,每人还是只有一个苹果,但如 果你有一种思想,我有一种思想,我们交换之后,每人就有两种思想。pyos 最初也是看到国外一位朋友写 的指南(tutorial)而起步的,在网上搜一下,国外有不少朋友在自己写操作系统,而且有很不错的成果,最重 要的是,这些成果都是开放的,你可以随意的取得,而且还有大量的教程、指南(tutorial)告诉你应当怎 么做,各种资料,相对来说都很丰富,还有不少新闻组、论坛,有不少热心人在上面讨论,我想这一切也 正是 Linux 诞生的根基。 科学研究需要一种氛围,系统开发也需要一种氛围,然而相对来说,国内的这种自由交流的氛围却要 淡很多,至少从我的感觉来说是这样,我处在一所全国前九所的大学当中,然而所能感受到的学术的氛围 却不是想象中的那么浓厚,特别是在本科阶段,基本上大体处于老师讲什么,学生学什么的氛围中,老师 不太指导学生怎么去更深层次的挖掘,怎么去自主的进行实验,而学生也似乎乐于单方面的接受,并着眼 于考试考什么;课余时间,更喜欢追求新兴技术,而对于相对底层的支撑技术不太感兴趣。曾经一位德高 望重的老师也对我说:做一些别人已有的东东,有什么意思?有什么价值?不过,我总认为,别人已有的, 是别人的,不是我们自己的,虽然别人已有的东东,我们或许不需要重新再去做,但我们应当知道别人是 怎么做的,去不去做与能不能做,是两个概念。 正是于此,诞生了哈工大纯 C 论坛,它追求一种纯粹的计算机科学技术,特别着眼于一些相对底层的 支撑技术,现在,我们又打算在每月的 28 日出版《哈工大·纯 C 论坛·电子杂志》,很高兴,找到了不 少志同道合者共同来完成此项工作,希望能由此营造一种向往已久的氛围。 参考文献 1. 《PS/2 技术参考》(Adam Chapweske 著,Roy Show 译)(网文,纯 C 论坛可以下载) 2. 《i8042——控制命令、寄存器、端口、键盘和鼠标命令》(好像是中国 Linux 论坛(http://www.linuxfo rum.net/)的网友 hyl 著)(网文,纯 C 论坛有转载) 3. 《BMP 文件格式分析》(网文,作者 yz,纯 C 论坛有转载)
本文档为【做一个支持图形界面的操作系统(下)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_247132
暂无简介~
格式:pdf
大小:543KB
软件:PDF阅读器
页数:26
分类:互联网
上传时间:2013-05-27
浏览量:33