【0】README
0.1) source code and text decription are from orange’s implemention of a os , and for complete code , please visit 我待会上传;
##**【1】 键盘输入缓冲区** * **step1)缓冲区的数据结构如下:** ![这里写图片描述](http://img.blog.csdn.net/20151008195844712) ![这里写图片描述](http://img.blog.csdn.net/20151008195852711)
-
step2)对缓冲区进行添加操作:(只是对 keyboard_handler 添加了一些代码, 上述荔枝图)
-
step3)修改后的init_keyboard
-
step4)初始化时钟中断
##**【2】用添加的新任务处理键盘操作**
- 终端任务:我们的任务不仅会处理键盘操作、还会处理屏幕输出等内容, 这些操作共同组成同一个任务——终端任务;
- keyboard_read():将扫描码从缓冲区读出,并打印;缓冲区的r_tail 指针移动, 而你是否记得将扫描码存入缓冲区 是 缓冲区的 head指针移动;
##**【3】解析扫描码** **Attention:**下面就是对 keyboard_read进行扩展了,像添加对小写字符,数字的处理, 后面是 F1~F12的键处理, shift键处理,home键的处理等等;
Conclusion)修改的代码内容包括:添加了键盘中断缓冲区的代码,修改了 keyboard_handler()函数 + init_keyboard()函数 + 对小写字母和数字的处理代码;
-
C1.1)我们给出修改后的代码调用过程(重点在于 keyboard_handler()函数 + init_keyboard()函数 ):
-
C1.2)如何取到用户键入的数据,以及显示它们;
-
C2)运行结果为:
3.1)处理shift、alt、ctrl
注意:要将键的左右两边加以区分,如左shift和右shift的功能是不同的;(上上图以及说明了)
3.2)处理所有按键
-
存在的问题-Problems 和 解决方法Solutions:
-
Problem1)如果扫描码更加复杂一些,比如超过3个字符,如今的程序还不足以很好地处理;
因为当一个扫描码有不止一个字符时, 实际上会产生不止一次中断。-
看个荔枝:如果我们按一下Shift + A,产生的 0x2A0x1E0x9E0xAA 是4次中断接收来的;
- step1) 我们的键盘控制器8042 接收来自 键盘编码器8048 传送过来的键入数据的相应扫描码;
- step2) 8042收到扫描码后,会把该扫描码 编码成 make code+break code的形式, 并将其放置到输入缓冲区中,而8042的 输入缓冲寄存器只有一个字节来存储扫描码;;
- step3) 8042告诉 中断控制寄存器8259A 产生中断, 交给键盘中断处理程序去执行;(如果此时键盘又有新的键被按下,键盘控制器8042 将不再接收 键盘编码器8048传送过来的扫描码,一直到缓冲区被清空,所以这就是为什么引入输入缓冲区的原因.)
-
我们再来个补充(对比假设):
- 假设1)添加键盘输入缓冲区(占用内存空间)后:只要键入数据,那么就会触发键盘中断处理程序,该程序会从 键盘控制器8042的输入缓冲寄存器中读取键入数据的扫描码,并存储在键盘输入缓冲区中(之前已经建立在内存空间中了),也即让8042的输入缓冲区被清空,这样8042才会接收 键盘编码器8048传送过来的键入数据的 扫描码;
- 假设2) 如果不添加键盘输入缓冲区(占用内存空间):只要键入数据,那么就会触发键盘中断处理程序,该程序会从 键盘控制器8042的输入缓冲寄存器中读取键入数据的扫描码,并显示该扫描码对应的数据;
- 假设2中的问题):如果CPU没有立即响应中断处理程序 怎么办? 这使得8042的输入缓冲区不能被清空,反正一句话,就是要尽快让键盘控制器8042的输入缓冲器清空,这样才能使得8042可以连续不断地接受8048 传送过来的扫描码;
-
-
Solution1)我们将 从键盘控制器 8042 的输入缓冲寄存器(只能缓冲一个字节的数据)中读取数据的代码从 keyboard_read 函数中抽取出来,并封装到 get_byte_from_kbuf()函数中; 这样对于扫描码比较长的字符来说,我们可以通过 keyboard_read 函数多次读取键盘缓冲区中的数据(键入数据的扫描码而已);
-
键盘缓冲区的作用(function)(干货):
- 有了键盘缓冲区, 8042 缓冲区 无需受到 task_tty 进程运行状况的影响,因为键盘中断处理程序 是将输入的数据 保存到内存缓冲区去了,这样键盘控制器8042的输入缓冲器被清空,可以继续接受8048传送过来的扫描码;
-
Problem2)关于非打印字符的问题: 如果按下 诸如 F1、F2这样的功能键,系统会把它当做可打印字符来处理,从而打印出一个奇怪的符号;
Solutions2)我们的意思是: keyboard_read这个函数只是 负责读取扫描码就可以了(一次或多次调用get_byte_from_kbuf 函数 ),至于如何处理, 不应该由它来负责(因为不是所有键入的字符都是需要打印字符, 如Ctrl、Shift、大写锁定键、Esc键等);所以,我们又将打印字符的代码抽取为 in_process ()函数, 在in_process()函数中,依据扫描码判断键入的字符是否需要打印;(具体代码调用如下图所示)
os如何处理键盘的所有按键,显示or不显示,显示是如何显示