1.实验目的

  • 加深对操作系统设备管理基本原理的认识,实践键盘中断、扫描码等概念;
  • 通过实践掌握 Linux 0.11 对键盘终端和显示器终端的处理过程。

2.实验内容

本实验的基本内容是修改 Linux 0.11 的终端设备处理代码,对键盘输入和字符显示进行非常规的控制。

在初始状态,一切如常。用户按一次 F12 后,把应用程序向终端输出所有字母都替换为“*”。用户再按一次 F12,又恢复正常。第三次按 F12,再进行输出替换。依此类推。

以 ls 命令为例:

正常情况:

1
2
# ls
hello.c hello.o hello

第一次按 F12,然后输入 ls:

1
2
# **
*****.* *****.* *****

第二次按 F12,然后输入 ls:

1
2
# ls
hello.c hello.o hello

第三次按 F12,然后输入 ls:

1
2
# **
*****.* *****.* *****

3.实验报告

完成实验后,在实验报告中回答如下问题:

  • 在原始代码中,按下 F12,中断响应后,中断服务程序会调用 func?它实现的是什么功能?
  • 在你的实现中,是否把向文件输出的字符也过滤了?如果是,那么怎么能只过滤向终端输出的字符?如果不是,那么怎么能把向文件输出的字符也一并进行过滤?

4.实验提示

本实验需要修改 Linux 0.11 的终端设备处理代码(kernel/chr_drv/console.c 文件),对键盘输入和字符显示进行非常规的控制。

4.1键盘输入处理过程

键盘 I/O 是典型的中断驱动,在 kernel/chr_drv/console.c 文件中:

1
2
3
4
5
void con_init(void)  //控制台的初始化
{
    // 键盘中断响应函数设为 keyboard_interrupt
    set_trap_gate(0x21, &keyboard_interrupt);
}

所以每次按键有动作,keyboard_interrupt 函数就会被调用,它在文件 kernel/chr_drv/keyboard.S(注意,扩展名是大写的 S)中实现。

所有与键盘输入相关的功能都是在此文件中实现的,所以本实验的部分功能也可以在此文件中实现。

简单说,keyboard_interrupt 被调用后,会将键盘扫描码做为下标,调用数组 key_table 保存的与该按键对应的响应函数。

4.2输出字符的控制

printf() 等输出函数最终都是调用 write() 系统调用,所以控制好 write(),就能控制好输出字符。

5.实验步骤

1.修改tty_io.c文件

进入linux-0.11/kernel/chr_drv目录,打开tty_io.c,添加如下代码,增加press_f12_handle函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int switch_show_char_flag = 0;
void press_f12_handle(void)
{
	if (switch_show_char_flag == 0)
	{
		switch_show_char_flag = 1;
	}
	else if (switch_show_char_flag == 1)
	{
		switch_show_char_flag = 0;
	}
}

img

2.修改keyboard.S文件

此文件和步骤1中的文件目录相同:

linux 0.11/chr_drv/keyboard.S 中将我们自定义的响应函数替代默认的func函数

1
.long press_f12_handle,none,none,none

image-20220412163040577

3.修改console.c文件

在console.c文件中增加如下代码

1
2
3
4
if (switch_show_char_flag == 1 && ( (c >= 48 && c<= 57) || (c>=65 && c<=90) || (c>=97 && c<=122) ) )
{
	c = '*';
}

此代码对应实验的核心要求 img

4.修改tty.h

此文件位于include/linux目录,添加如下代码:

1
2
extern int switch_show_char_flag;
void press_f12_handle(void);

img

修改完后将其复制到hdc中

5.编译运行Linux

在进入系统后,输入ls -l发现字符正常显示,此时再输入F12然后输入ls -l命令,发现所有的字符回显均变成了*号,实验结果符合预期。 img

遇到的问题

按下F12没反应

image-20220412161132774

linux 0.11/chr_drv/keyboard.S 中将我们自定义的响应函数替代默认的func函数

1
2
3
4
5
.long none,none,do_self,func	/* 54-57 sysreq ? < f11 */
//.long func,none,none,none		/* 58-5B f12 ? ? ? */
.long press_f12_handle,none,none,none		/* 58-5B f12 ? ? ? */
.long none,none,none,none		/* 5C-5F ? ? ? ? */
.long none,none,none,none		/* 60-63 ? ? ? ? */

回答问题

  1. 将F12转义成转义字符序列 [ [ L , 对F1-F12处理类似 [ [ A -> [ [ L

  2. 实现了文件输出的过滤,该过滤是通过修改fs/file_dev.c中file_write()函数,实现代码类似tty_write()函数。 具体修改如下:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    while (c-->0)
    	{
    		tmp = get_fs_byte(buf++);
    		if(f12_flag == 1)
    		{
    			if((tmp>='A'&&tmp<='Z')||(tmp>='a'&&tmp<='z')||(tmp>='0'&&tmp<='9'))
    						tmp = '*';
    		}
    	*(p++) = tmp;
    }
    

    如果只过滤终端输出字符,则可以去掉file_write()修改即可;