哈工大-操作系统-HitOSlab-李治军-实验7-终端设备的控制

实验7-终端设备的控制

实验内容请查看实验指导手册

绪论

根据题目的要求,可以想到一共需要改两个地方:

第一个地方:我们首先需要把F12原有的功能屏蔽掉,然后改成我们要用到的“开关”功能,即设定一个变量flag表示开关标记,按一次F12后flag变成1,再按一次flag变成0,再按又变成1。

第二个地方:在字符输出到显示器前,根据flag的值来决定显示正常字符或者显示*字符。

一、实验内容

(1)修改linux-0.11/kernel/chr_drv/keyboard.S文件

正常情况下在linux0.11中,当按下F1~F12的功能键后会调用show_stat函数来显示系统中当前进程状态,对应代码在kernel/chr_drv/keyboard.S文件中,第210行func函数中:

func:
    push %eax
	push %ecx
	push %edx
	call show_stat
	pop %edx
	pop %ecx
	pop %eax

将语句call show_stat删除掉,因为我们不需要原有的F12所对应的按键功能了。

(2)修改tty_io.c文件

该文件中的copy_to_cooked函数是处理ASCII字符的函数。先在该函数的定义外面增加全局变量如下,flag即开关标志,f1~f3是等会判断要用到的一些中间变量。

int flag = 0;
int f1=0,f2=0,f3=0;

然后在copy_to_cooked函数中添加一部分内容,使其识别到F12对应的那四个ASCII字符后(F12这个功能键的扫描码是ESC、[、[、L,它们对应的ASCII码是27,91,91,76),改变flag的值,然后continue跳过本轮循环(否则会继续执行后面的代码从而导致按下F12时会显示一个字符L),如下:

void copy_to_cooked(struct tty_struct * tty)
{
    
    
    signed char c; 
    while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
    
    
        GETCH(tty->read_q,c);
//下面开始添加代码
        if(c==27){
    
    
            f1 = 1;
            f2=f3=0;
        }
        else if(f1==1 && f2==0 && c==91){
    
    
            f2 = 1;
        }
        else if(f2==1 && f3==0 && c==91){
    
    
            f3 = 1;
        }
        else if(f3==1 && c==76 && flag==0){
    
    
            flag = 1;
            f1=f2=f3=0;
            continue;
        }
        else if(f3==1 && c==76 && flag==1){
    
    
            flag = 0;
            f1=f2=f3=0;
            continue;
        }
        else{
    
    
            f1=f2=f3=0;
        }
//添加代码结束

(3)修改console.c文件

在(kernel/chr_drv/console.c)文件中定义的con_write()函数中,它对队列中的字符进行了一些处理后,最终放入显存。如下是将字符变量c放入显存的代码:

__asm__("movb attr,%%ah\n\t"
"movw %%ax,%1\n\t"
::"a" (c),"m" (*(short *)pos)
);

所以我们只需要在这段代码之前加上一条if语句,判断flag如果是1,则把要放入显存中的字符变成星号,修改后如下(需要在该函数中先通过extern int flag这条语句来声明外部变量 ,因为flag在现在的这个文件中还没有定义过):

/* 在文件的头部添加变量声明语句 */
extern int flag;
/* ... */
//添加开始
while(nr--){
    
    
/* ... */
	if(flag == 1){
    
    
    	c = '*';
	}
	//添加结束
	__asm__("movb attr,%%ah\n\t"
	"movw %%ax,%1\n\t"
	::"a" (c),"m" (*(short *)pos)
	);
/* ... */

(4)编译测试

保存所有修改过的文件,使用make all指令重新编译内核。编译成功后,返回上一级菜单,使用./run启动Bochs:

(1)启动Bochs:
在这里插入图片描述

(2)第一次按F12
在这里插入图片描述
(3)第二次按F12
在这里插入图片描述

二、回答问题

1.在原始代码中,按下 F12,中断响应后,中断服务程序会调用 func,它实现的是什么功能?

正常情况下打开模拟器中,按下功能键F12即可显示内核栈中各个进程的状态信息,而当把func中的call show_stat屏蔽掉后,再按下F12就什么也没有了,可见func实现的功能就是调用show_stat函数来显示内核栈中各个进程的状态信息。

2.在你的实现中,是否把向文件输出的字符也过滤了?

只过滤了向终端输出的字符,向文件输出的字符没有被过滤。
因为我们最后修改的是控制向显存输出的con_write()函数,使其当flag=1的时候向显存输出星号。
如果要过滤掉向文件输出的字符的话,需要找到对应的那个控制向文件输出的函数并修改。

Guess you like

Origin blog.csdn.net/qq_42518941/article/details/120443385