操作系统键盘---17
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统键盘---17相关的知识,希望对你有一定的参考价值。
操作系统键盘---17
终端设备包括显示器和键盘
让外设工作起来
关于键盘的故事从哪里开始?
如何使用键盘?
- 对于使用者(人): 敲键盘、看结果
- 对于操作系统: “等着”你敲键盘,敲了就中断
所以故事该从键盘中断开始,从中断初始化开始…
void con_init(void) //应为键盘也是console的一部分
//键盘中断对应的是21号中断---21号中断对应的处理程序为keyboard_interrupt
set_trap_gate(0x21, &keyboard_interrupt);
在kernel/chr_drv/keyboard.S中
.globl _keyboard_interrupt
_keyboard_interrupt:
//通过inb指令从外设端口读取数据
inb $0x60,%al //从端口0x60读扫描码
call key_table(,%eax,4) //调用key_table+eax*4
... push $0 call _do_tty_interrupt
处理扫描码key_table+eax*4
- key_table是一个函数数组
在kernel/chr_drv/keyboard.S中
key_table:
//do_self:显示字符通常都 用此函数处理!
.long none,do_self,do_self,do_self //扫描码00-03
.long do_self, ...,func, scroll, cursor 等等
- 扫描码02对应按键1;01对应ESC;12对应E等等
mode: .byte 0
do_self:
lea alt_map,%ebx
testb $0x20,mode //alt键是否同时按下 jne 1f
lea shift_map,%ebx testb $0x03,mode jne 1f
//找到映射表,如a的key_map映射为a,而shift_map映射为A
//将key_map起始地址赋值给ebx
lea key_map,%ebx
1:
从key_map中取出ASCII码
#if defined(KBD_US)
key_map: .byte 0,27 .ascii “1234567890-=“ ...
//同时按了shift键,需要转换成大写
shift_map: .byte 0,27 .ascii “!@#$%^&*()_+” ...
#elif defined(KBD_GR) ...
- 继续do_self,从1:开始,ebx放的是map起始地址
1: movb (%ebx,%eax),%al //扫描码索引,ASCII码àal
orb %al,%al je none //没有对应的ASCII码
testb $0x4c,mode //看caps是否亮
je 2f cmpb $’a,%al jb 2f
cmpb $’,%al ja 2f subb $32,%al //变大写
2:testb $??,mode //处理其他模式,如ctrl同时按下
//得到ascii码后,会将得到的ascii码加入put_queue中
3:andl $0xff,%eax call put_queue
none:ret
put_queue将ASCII码放到? con.read_q
//中端设备分为输入和输出设备,因此每个外设都对应两个队列,一个输入队列,一个输出队列
//我们这里读取键盘输入,显然应该是read_q队列
struct tty_queue *table_list[]=
&tty_table[0].read_q,
&tty_table[0].write_q;
...
;
put_queue:
//拿到对应的队列---这里是输入队列read_q
movl _table_list,%edx
//拿到对应队列头部地址
movl head(%edx),%ecx
//将ascii码输出到队列的头部
1:movb %al,buf(%edx,%ecx)
- 到目前为止还差什么? ---->一般读取完键盘输入后,还需要回显字符
void do_tty_interrupt(int tty) //上面传来的是0
//回显到什么设备上去---这里根据设备号索引,去tty_table中确定具体的设备
copy_to_cooked(tty_table+tty);
void copy_to_cooked(struct tty_struct *tty)
//从当前设备的输入队列中,获取需要回显的字符
GETCH(tty->read_q,c);
if(L_ECHO(tty)) //回显,也可以不回显--有些字符不能显示,就不进行回显
//将从输入队列读取的字符再放入当前设备对应的输出队列中去
PUTCH(c,tty->write_q);
tty->write(tty); //立刻显示到屏幕上
PUTCH(c,tty->secondary); //完成copy_to_cooked---对字符进行一些处理后放入tty->secondary队列中去
... wake_up(&tty->secondary.proc_list);
向屏幕输出 tty->write(tty) ,请看前一节内容
键盘处理…
- 键盘按下一个按键后,对应触发键盘中断处理程序
- 通过扫描码得到对应的ascii码,然后将ascii码加入read_q队列中去
- do_tty_interrupt函数负责读取read_q队列
- 判断是否需要显示当前字符到屏幕上去,如果需要,则从read_q队列读取对应的字符,加入write_q队列中,然后调用tty_write输出到屏幕
- 对字符进行一些处理后,加入tty->secondary队列中去(具体是什么处理,感兴趣可以自行查询资料)
如果将键盘输入和显示器输出结合起来,就如下图所示:
以上是关于操作系统键盘---17的主要内容,如果未能解决你的问题,请参考以下文章