“操作系统实验”实验报告

终端设备的控制

实验名称:终端设备的控制

实验日期: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;
```![图片描述](https://dn-simplecloud.shiyanlou.com/courses/uid1682555-20210708-1625745614080)
然后在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; }

![图片描述](https://dn-simplecloud.shiyanlou.com/courses/uid1682555-20210708-1625745899408)
在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;这条语句来声明外部变量
![图片描述](https://dn-simplecloud.shiyanlou.com/courses/uid1682555-20210708-1625746094829)
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的时候向显存输出星号。如果要过滤掉向文件输出的字符的话,需要找到对应的那个控制向文件输出的函数并修改。

最新评论
暂无评论~