linux键盘IO探究和实验[基于哈工大操作系统实验]

本文以哈工大操作系统实验为背景,深入解析Linux0.11下键盘输入的实现原理,包括键盘中断处理、字符传递路径。通过修改kernel源码,实现F12键功能,避免L字符的异常输出,并探讨更高级的解决方案,确保仅F12键改变状态,同时处理实验要求的文件限制问题。
摘要由CSDN通过智能技术生成

    我们使用的键盘,看似非常简单自然,但是其功能的实现却相当有学问,本文将以哈工大操作系统IO设备实验为基础,讲解一下linux0.11下键盘功能的实现,和简单修改的方法。

一,实现原理

键盘功能主要由如下几个程序实现:

keyboard.S     : 大S,引入c++预编译,使得汇编程序可以用预处理命令。接受键盘中断反馈的键盘码。

tty_io.c           :读汇编程序吃剩下的东西,嚼完往下扔。

console.c       :对了,嚼完的被他接住了....他再嚼两下,吐到您的屏幕上。

 

也就是说,一个字符从敲击至到达屏幕,经过的路程简要来说是这样的:

keyboard.S   ---read_queue---->  tty_io.c   --------write_queue----->  console.c  ----调用__asm__()---> 屏幕。

不关心这些东西,想直接过实验的同学可以直接跳到五

二,keyboard.S 程序和 f12 功能键

先看一下keyboard.s程序:

 

/*
 *  linux/kernel/keyboard.S
 *
 *  (C) 1991  Linus Torvalds
 *	Thanks to Alfred Leung for US keyboard patches
 *		Wolfgang Thiel for German keyboard patches
 *		Marc Corsini for the French keyboard
 */
#include <linux/config.h>
.text
.globl keyboard_interrupt
/*
 * these are for the keyboard read functions
 */
size	= 1024		/* must be a power of two ! And MUST be the same			   as in tty_io.c !!!! */
head = 4
tail = 8
proc_list = 12
buf = 16
mode:	.byte 0		/* caps, alt, ctrl and shift mode */
leds:	.byte 2		/* num-lock, caps, scroll-lock mode (nom-lock on) */
e0:	.byte 0
/*
 *  con_int is the real interrupt routine that reads the
 *  keyboard scan-code and converts it into the appropriate下方的中断服务函数,将按键扫描码,转换成ASCII码
 *  ascii character(s).
 */
keyboard_interrupt:/*这个是键盘中断函数,没几行代码,每次按键盘,就进入这里*/
	pushl %eax
	pushl %ebx
	pushl %ecx
	pushl %edx
	push %ds
	push %es
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	xor %al,%al		/* %eax 寄存器放的,就是这次按键按下的按钮编码 */
	inb $0x60,%al
	cmpb $0xe0,%al     /* 简单比较处理一下 */
	je set_e0
	cmpb $0xe1,%al
	je set_e1
	call key_table(,%eax,4)/* 将 eax 按钮号码交给 【key_table】 映射到相应处理函数。keytable 在程序末尾*/
	movb $0,e0
e0_e1:	inb $0x61,%al
	jmp 1f
1:	jmp 1f
1:	orb $0x80,%al
	jmp 1f
1:	jmp 1f
1:	outb %al,$0x61
	jmp 1f
1:	jmp 1f
1:	andb $0x7F,%al
	outb %al,$0x61
	movb $0x20,%al
	outb %al,$0x20
	pushl $0
	call do_tty_interrupt
	addl $4,%esp
	pop %es
	pop %ds
	popl %edx
	popl %ecx
	popl %ebx
	popl %eax
	iret
set_e0:	movb $1,e0
	jmp e0_e1
set_e1:	movb $2,e0
	jmp e0_e1
/*
 * This routine fills the buffer with max 8 bytes, taken from
 * %ebx:%eax. (%edx is high). The bytes are written in the
 * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
 */
put_queue:               /*写队列函数,调用时,把接收到的一组按钮吐到read_queue里面给tty_io*/
	pushl %ecx
	pushl %edx
	movl table_list,%edx		# read-queue for console
	movl head(%edx),%ecx
1:	movb %al,buf(%edx,%ecx)
	incl %ecx
	andl $size-1,%ecx
	cmpl tail(%edx),%ecx		# buffer full - discard everything
	je 3f
	shrdl $8,%ebx,%eax
	je 2f
	shrl $8,%ebx
	jmp 1b
2:	movl %ecx,head(%edx)
	movl proc_list(%edx),%ecx
	testl %ecx,%ecx
	je 3f
	movl $0,(%ecx)
3:	popl %edx
	popl %ecx
	ret
                          /*控制特殊键盘按钮的处理函数 ,alt shift ctrl 什么的*/
ctrl:	movb $0x04,%al
	jmp 1f
alt:	movb $0x10,%al
1:	cmpb $0,e0
	je 2f
	addb %al,%al
2:	orb %al,mode
	ret
unctrl:	movb $0x04,%al
	jmp 1f
unalt:	movb $0x10,%al
1:	cmpb $0,e0
	je 2f
	addb %al,%al
2:	notb %al
	andb %al,mode
	ret
lshift:
	orb $0x01,mode
	ret
unlshift:
	andb $0xfe,mode
	ret
rshift:
	orb $0x02,mode
	ret
unrshift:
	andb $0xfd,mode
	ret

caps:	testb $0x80,mode
	jne 1f
	xorb $4,leds
	xorb $0x40,mode
	orb $0x80,mode
set_leds:
	call kb_wait
	movb $0xed,%al		/* set leds command */
	outb %al,$0x60
	call kb_wait
	movb leds,%al
	outb %al,$0x60
	ret
uncaps:	andb $0x7f,mode
	ret
scroll:
	xorb $1,leds
	jmp set_leds
num:	xorb $2,leds
	jmp set_leds
/*
 *  curosr-key/numeric keypad cursor keys are handled here.
 *  checking for numeric keypad etc.
 */
cursor:                    /*光标处理,不用管,代码省略*/
...
...
cur2:			/* e0 forces cursor movement */
...

cur:	
...
ok_cur:
...
#if defined(KBD_FR)
num_table:
	.ascii "789 456 1230."
#else
num_table:
	.ascii "789 456 1230,"
#endif
cur_table:
	.ascii "HA5 DGC YB623"
/*
 * 下面这个函数有意思了,他就是处理function1-12的函数,从下面的映射表key_table可以看出,任意F被按下都跳到这里处理
 */
func:
	pushl %eax
	pushl %ecx
	pushl %edx
	call show_stat  /*这里调用了一个位于【sched.c】中的c语言系统调用函数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值