实验名称:终端设备的控制
实验日期:2021/7/8
班级:物联网194
姓名:杨毅
学号:1930110740
一·实验目的
加深对操作系统设备管理基本原理的认识,实践键盘中断、扫描码等概念;
通过实践掌握 Linux 0.11 对键盘终端和显示器终端的处理过程。
二·实验环境
1、硬件环境是 IA-32(x86) 架构的 PC 机(在实验楼的环境中就是右侧的窗口)
2、主要软件环境是 Bochs + gcc + 你最喜欢的编辑器 / IDE + 你最喜欢的操作系统 + Linux 0.11 源代码
三·实验内容
本实验的基本内容是修改 Linux 0.11 的终端设备处理代码,对键盘输入和字符显示进行非常规的控制。
在初始状态,一切如常。用户按一次 F12 后,把应用程序向终端输出所有字母都替换为“*”。用户再按一次 F12,又恢复正常。第三次按 F12,再进行输出替换。依此类推。
以 ls 命令为例:
正常情况:
# ls
hello.c hello.o hello
copy
copy
第一次按 F12,然后输入 ls:
# **
*****.* *****.* *****
copy
copy
第二次按 F12,然后输入 ls:
# ls
hello.c hello.o hello
copy
copy
第三次按 F12,然后输入 ls:
# **
*****.* *****.* *****
copy
四·实验过程及数据记录
准备环境
$ cd /home/shiyanlou/oslab/
$ tar -zxvf hit-oslab-linux-20110823.tar.gz \
-C /home/shiyanlou/
copy
F12这个键应该是对应某个功能的,我们首先需要把它原有的功能屏蔽掉,然后改成我们要用到的“开关”功能,即设定一个变量flag表示开关标记,按一次F12后flag变成1,再按一次flag变成0,再按又变成1
先把kernel/chr_drv/keyboard.S文件中的func函数中那条指令call show_stat注释掉,我们不再需要F12的这个功能了
func:
push %eax
push %ecx
push %edx
//call show_stat
pop %edx
pop %ecx
pop %eax
copy
然后修改kernel/chr_drv/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字符后,改变flag的值,然后continue跳过本轮循环(否则会继续执行后面的代码从而导致按下F12时会显示一个字符L),如下。
copy
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; }

在kernel/chr_drv/console.c文件中定义的con_write()函数中,它对队列中的字符进行了一些处理后,最终放入显存。如下是将字符变量c放入显存的代码:
copy
asm("movb attr,%%ah\n\t" "movw %%ax,%1\n\t" ::"a" (c),"m" (*(short *)pos) );
在这段代码之前加上一条if语句,判断flag如果是1,则把要放入显存中的字符变成星号,修改后如下,需要在该函数中先通过extern int flag;这条语句来声明外部变量

copy
//添加开始 if(flag == 1){ c = ''; } //添加结束 asm("movb attr,%%ah\n\t" "movw %%ax,%1\n\t" ::"a" (c),"m" ((short *)pos) );
```
编译make all
运行./run
测试
以 ls 命令为例:
第一次按 F12,然后输入 ls:
第二次按 F12,然后输入 ls:
第三次按 F12,然后输入 ls:
五·实验结果分析
修改 Linux 0.11 的终端设备处理代码,对键盘输入和字符显示进行非常规的控制。在初始状态,一切如常。用户按一次 F12 后,把应用程序向终端输出所有字母都替换为“*”。实验成功
六·实验心得
通过本次实验,我学会修改 Linux 0.11 的终端设备处理代码,对键盘输入和字符显示进行非常规的控制。
在初始状态,一切如常。用户按一次 F12 后,把应用程序向终端输出所有字母都替换为“*”。用户再按一次 F12,又恢复正常。第三次按 F12,再进行输出替换。
七·回答问题
1.在原始代码中,按下 F12,中断响应后,中断服务程序会调用 func?它实现的是什么功能?
答:正常情况下打开模拟器中,按下功能键F12即可显示内核栈中各个进程的状态信息,而当把func中的call show_stat屏蔽掉后,再按下F12就什么也没有了,可见func实现的功能就是调用show_stat函数来显示内核栈中各个进程的状态信息。
2.在你的实现中,是否把向文件输出的字符也过滤了?如果是,那么怎么能只过滤向终端输出的字符?如果不是,那么怎么能把向文件输出的字符也一并进行过滤?
答:只过滤了向终端输出的字符,向文件输出的字符没有被过滤。因为我们最后修改的是控制向显存输出的con_write()函数,使其当flag=1的时候向显存输出星号。如果要过滤掉向文件输出的字符的话,需要找到对应的那个控制向文件输出的函数并修改。
学习时间 42分钟
操作时间 32分钟
按键次数 3291次
实验次数 3次
报告字数 3974字
是否完成 完成