




已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
操作系统课程设计一、实验选题1二、模块整体功能介绍及主要目标1三、头文件的分析2四、数据结构的分析21、数组tty_table22、tty_struct 数据结构23、tty 等待队列数据结构34、各个数据结构间的关系图3五、函数的分析41、采用中断驱动的I / O设备键盘的循环周期42、键盘中断处理程序53、ctrl和alt键的处理74、caps、scroll、num键的处理85、数字小键盘的处理116、减号键的处理137、功能键的处理148、do_self的处理159、左,右shift键的处理16六、分析体会及亮点说明16七、参考文献20一、实验选题实验题目是:Linux0.11字符设备驱动中的键盘驱动程序源代码分析,这部分涉及到操作系统的中断、I/O应用接口、I/O子系统等相关知识,程序源代码参考Linux0.11中kernel目录下的keyboard.s文件。二、模块整体功能介绍及主要目标该模块键盘中断处理程序 keyboard.s 主要用于读入用户键入的字符并放入read_q 缓冲队列中。其具体实现机制是:当用户在键盘上键入了一个字符时,会引起键盘中断响应(中断请求信号IRQ1,对应中断号INT 33),此时键盘中断处理程序就会从键盘控制器读入对应的键盘扫描码,然后根据使用的键盘扫描码映射表译成相应字符,放入tty 读队列read_q 中。然后调用中断处理程序的C函数do_tty_interrupt(),它又直接调用行规则函数copy_to_cooked()对该字符进行过滤处理,并放入tty 辅助队列secondary 中,同时把该字符放入tty 写队列write_q 中,并调用写控制台函数con_write()。此时如果该终端的回显(echo)属性是设置的,则该字符会显示到屏幕上。do_tty_interrupt()和copy_to_cooked () 函数在tty_io.c 中实现。用图描述如下:三、头文件的分析#include / 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。在这里还可以定义你的键盘类型:KBD_FINNISH 是芬兰键盘、KBD_US 是美式键盘、KBD_GR 是德式键盘、KBD_FR 是法式键盘。如 #define KBD_US 表示定义美式键盘。通常,Linux 能够在启动时从BIOS 中获取驱动器德参数,但是若由于未知原因而没有得到这些参数时,会使程序束手无策。对于这种情况,你可以定义HD_TYPE,其中包括硬盘的所有信息。HD_TYPE 宏应该象下面这样的形式:#define HD_TYPE head, sect, cyl, wpcom, lzone, ctl对于有两个硬盘的情况,参数信息需用逗号分开:#define HD_TYPE h,s,c,wpcom,lz,ctl , h,s,c,wpcom,lz,ctl 如果你想让BIOS 给出硬盘的类型,那么只需不定义HD_TYPE。这是默认操作。四、数据结构的分析1、数组tty_table使用了一个数组tty_table来保存系统中键盘的信息。每个数组项是一个数据结构tty_struct,用来保存键盘当前状态和正在处理的数据。用C语言描述如下:extern struct tty_struct tty_table; / tty 结构数组2、tty_struct 数据结构该终端驱动程序主要使用了一个tty_struct 数据结构,在该结构中含有三个功能不同的字符缓冲队列。一个缓冲队列read_q 用来存放用户键入(读入)的原始字符数据;一个缓冲队列write_q用来存放输出到终端(写到终端)去的数据;还有一个缓冲队列secondary 用来存放已经“加工”过的读入数据,这是在行规则程序把原始数据中的特殊字符如删除(backspace)字符变换后的“熟”(cooked)输入数据。tty 数据结构用C描述如下:struct tty_struct struct termios termios; / 终端io 属性和控制字符数据结构。int pgrp; / 所属进程组。int stopped; / 停止标志。void (*write)(struct tty_struct * tty); / tty 写函数指针。struct tty_queue read_q; / tty 读队列。struct tty_queue write_q; / tty 写队列。struct tty_queue secondary; / tty 辅助队列(存放规范模式字符序列),/ 可称为规范(熟)模式队列。; 3、tty 等待队列数据结构tty 等待队列数据结构用C语言描述如下:struct tty_queue unsigned long data; / 等待队列缓冲区中当前数据指针(字符数?)。/ 对于串口终端,则存放串口端口地址。unsigned long head; / 缓冲区中数据头指针。unsigned long tail; / 缓冲区中数据尾指针。struct task_struct * proc_list; / 等待进程列表。char bufTTY_BUF_SIZE; / 队列的缓冲区。;4、各个数据结构间的关系图五、函数的分析1、采用中断驱动的I / O设备键盘的循环周期键盘是通过中断来实现的,每当键盘控制器接收到用户的一个键盘操作时,就会向中断控制器发出一个键盘中断请求信号IRQ1.当CPU响应请求就会执行键盘中断处理程序,对于整个系统其流程如下图所示:2、键盘中断处理程序这是键盘中断处理程序的入口处,该中断处理程序首先从端口0x60读取当前按键的扫描码。然后判断该扫描码是否是0xe0或0xe1,如果是的话就立刻对键盘控制器作出应答,并向中断控制器发送中断结束(EOI)信号,以允许键盘控制器能继续产生中断信号,从而让我们来接收后续的字符。如果接收到的扫描码不是这两个特殊扫描码,我们就根据扫描码值调用按键跳转表key_table中相应按键处理程序,把扫描码对应的字符放入字符缓冲队列read_q中。然后,在对键盘控制器作出应答并发送EOI信号之后,调用函数do_tty_interrupt()(实际上是调用copy)_to_cooked ())把read_q中的字符经过处理后放到secondary辅助队列中。源程序见keyboard.s的2771行,程序流程如下图:3、ctrl和alt键的处理对于用于具有相同功能的左右ctrl、allt键,它们被按下时,发送的码子是不一样的。比如:左控制键ctrl 位置是0x1d(对于PC/XT),则右边的控制键就是0xe0,0x1d。因此,若有ctrl 或 alt键按下则要分别设置模式标志中相应位。如果该扫描码之前收到过 0xe0 扫描码(e0 标志置位),则说明按下的是键盘右边的ctrl 或alt 键,则对应设置ctrl 或alt在模式标志mode 中的比特位。源程序见keyboard.s的101108行,程序流程如下图:当接收到ctrl 或alt 键松开的扫描码,对应复位模式标志mode 中的比特位。在处理时要根据e0 标志是否置位来判断是否是键盘右边的ctrl 或alt 键。源程序见keyboard.s的109117行,程序流程如下图:4、caps、scroll、num键的处理当接收到caps键按下的扫描码时,通过mode中位7可以知道caps键当前是否正处于在按下状态。若是则返回,否则就翻转mode标志中caps键按下的比特位(位6)和 leds标志中 capslock比特位(位2),设置mode标志和中caps键已按下标志位(位7),并调用set_led开启或关闭LED指示器。当接收到 scroll 键按下的扫描码时,翻转leds中对应位(位0),并且根据leds标志重新开启或关闭LED指示器。当接收到 num 键按下的扫描码时,翻转leds中对应位(位1),并且根据leds标志重新开启或关闭LED指示器。源程序见keyboard.s的132152行,程序流程如下图:子程序kb_wait 用于等待键盘控制器缓冲空。不存在超时处理 - 如果缓冲永远不空的话,程序就会永远等待(死掉). 源程序见keyboard.s的393399行,程序流程如下图: 5、数字小键盘的处理 把字符放到缓冲队列是通过子程序put_queue实现的该子程序把ebx:eax 中的最多8 个字符添入缓冲队列中。(edx 是所写入字符的顺序al,ah,eal,eah,bl,bh.直到eax 等于0。源程序见keyboard.s的7899行,程序流程如下图:重启是通过调用子程序reboot实现的,该子程序通过设置键盘控制器,向复位线输出负脉冲,使系统复位重启(reboot)。源程序见keyboard.s的404409行,程序流程如下图:6、减号键的处理7、功能键的处理8、do_self的处理do_self 用于处理“普通”键,也即含义没有变化并且只有一个字符返回的键,源程序见keyboard.s的274305行,程序流程如下图: 9、左,右shift键的处理当接收到左或右shift 键按下的扫描码,对应置位模式标志mode 中的比特位。当接收到左或右shift 键松开的扫描码,对应复位模式标志mode 中的比特位。 Shift键处理程序六、分析体会及亮点说明这次我分析的这段代码keyboard.s是用AT汇编写的,而我们以前接触的都是Intel 汇编,通过老师的指导和查阅一些相关资料我对这两种汇编语言有了一定的了解,因此我读键盘的那段内核代码还比较轻松,我在读代码的时候也发现了一些问题,最初我对caps 键的处理有些疑惑,我认为caps 键和num 键的处理应该是一样的,可是在Linux 0.11中caps 键作了特殊处理,开始我怀疑代码错了,后来查阅了一些资料,上面都是这样处理的,后来仔细想想,发现我忽略了一个问题,当caps 键正处于按下状态时候,我们按下键盘上的字母键,输入的字母就是大写的,这个功能对于num而言是没有的,因此在mode 中要设置标志位 7表示caps是否正处于按下状态。相应地,当接收到caps 键扫码进行处理。通过mode中位7可以知道caps键当前是否正处于在按下状态。若是则返回,否则就翻转mode标志中caps键按下的比特位(位6)和 leds标志中 capslock比特位(位2),设置mode标志和中caps键已按下标志位(位7),并调用set_led开启或关闭LED指示器。当接收到 scroll 键按下的扫描码时,翻转leds中对应位(位0),并且根据leds标志重新开启或关闭LED指示器。当接收到 num 键按下的扫描码时,翻转leds中对应位(位1),并且根据leds标志重新开启或关闭LED指示器。在这次课程设计的过程中,使我更加懂得“细致”对于我们学习知识相当重要。此外,为了说明我对按键处理过程的理解,下面我举例两个例子说明一下:1、考虑在caps键未锁定的情况下我们按下字母键a时,会触发哪些事件?按下键 a 时,键盘控制器会向中断控制器发出一个中断请求信号IRQ1,并将该键对应的键扫码 0x 1e 送入输入缓冲器(端口地址0x60),CPU响应中断,进入键盘的中断服务处理程序_keyboard_interrupt,该处理程序首先从端口 0x60 读取这个键的扫描码 0x 1e ,由于这个键扫码不等于 0xe0且不等于0xe1,所以直接调用按键跳转表key_table中 1E 对应的子程序do_self,do_self会检测到 alt 和 shift 键均位按下,就到普通映射表 key_map 中根据扫描码取出相应的ASCII码 a ,由于alt 键都未按下,caps 也未锁定,所以直接将a放到读缓冲队列(read_q)中,然后返回到_keyboard_interrupt中断服务子程序中,向中断控制器发送中断结束信号,将收到的数据转换成规范模式并保存在规范字符缓冲队列中(call _do_tty_interrupt)。具体流程如下图:当a键松开时,也会产生中断,并产生0x90扫描码。调用键盘中断处理程序_keyboard_interrupt,它根据键扫码进行相应操作;不过此时的在跳转表中对应是none的地址,不做任何事就返回到_keyboard_interrupt,进行与前面键按下相同的操作。具体流程如下图:2、考虑同时按下右shift和“ 2”键时,会触发哪些事件?右边的shift被按下时,会发送0xe0和其对应的键扫码0x36,在接收到0xe0时将设置e0标志为0,再向中断控制器发送中断结束信号,将收到的数据转换成规范模式并保存在规范字符缓冲队列中(call _do_tty_interrupt)。接下来接收到的是键扫码0x36,由于这个键扫码不等于 0xe0且不等于0xe1,跳转表key_tabke中对应的是rshift子程序的入口地址,调用rshift子程序设置mode中的1位后返回到_keyboard_interrupt,向中断控制器发送中断结束信号,将收到的数据转换成规范模式并保存在规范字符缓冲队列中(call _do_tty_interrupt)。然后收到 ” 2” 键按下的中断,根据接收到的键扫码 0x02 调用按键跳转表key_table中 0x02 对应的子程序do_self,do_self通过mode标志检测到有shift
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论