操作系统实验 2.3系统调用:linux-0.11-lab “为版本0内核增加一个系统调用getjiffies” 和 “在用户程序中使用新增的系统调用”

目录

一、为版本0内核增加一个系统调用getjiffies

打开vscode,在如图所示位置打开~/os/linux-0.11-lab/0文件夹
在这里插入图片描述
在这里插入图片描述

(一)分析思路

1.定义getjiffies系统调用

题目中给的提示:进入到unistd.h文件中
在这里插入图片描述

阅读代码,可以发现上图划线处有个系统调用名为getpid:返回当前进程号——这与我们期望实现的功能类似:通过系统调用返回jiffies值。
于是此时希望模仿getpid系统调用,实现getjiffies系统调用。
vscode左侧搜索栏中搜索关键词getpid,仿照即可。
在这里插入图片描述

主要修改下图划线的三个文件
在这里插入图片描述

2.在系统启动时自动调用该系统调用并输出结果

由于下图所示的任务要求
在这里插入图片描述
系统启动时将调用0/linux/init/main.c文件,且其中的main函数中下图圈出位置的if`语句中的init函数完成初始化的显示输出操作。

在这里插入图片描述
所以需要在main.cinit函数中调用getjiffies系统调用。(也可以进入bochs虚拟机中在/etc/rc中调用getjiffies,即在文件的最后写入getjiffies,这样的话打印结果就可以符合题目要求了,二者选一做)
在这里插入图片描述

(二)实验过程

1.添加系统调用号

(1)unistd.h

在调用号的最后添加#define __NR_getjiffies 87
在这里插入图片描述

(2) 修改sys.hsys_call_tablesystem_call.snr_system_calls

参考博文:CSDN-为Linux0.11添加系统调用(作者)-为Linux0.11添加系统调用
(注:system_call.s0/linux/kernel/目录下)
这里的nr_system_calls值为88,不能为87,因为系统调用数量为88个?不理解没有修改前的nr_system_calls的值为什么为86,最后一个系统调用usrlib没有用到吗。
在这里插入图片描述

2.定义getjiffies系统调用函数

可以看到jiffies的变量类型为long
在这里插入图片描述

(1)仿照getpidunistd.h中声明函数

在这里插入图片描述

在这里插入图片描述

(2)在sched.c`文件中定义函数主体

仿照getpid系统调用
在这里插入图片描述

创建``getjiffies!系统调用

在这里插入图片描述

3.在系统启动时自动调用getjiffies系统调用并输出结果

阅读main.c代码,可以在文件的开始位置发现main.c中调用的系统调用,如forkpause都经过下图划线位置的__always_inline _syscall0的操作,仿照该操作调用getjiffies系统调用。
在这里插入图片描述
在这里插入图片描述
init函数中打印信息。
在这里插入图片描述

(三)调试验证

进入~/os/linux-0.11-lab/0/linux
执行下列命令:

make clean;make
cd ../..
./run

得到如下图所示的输出,(虽然打印的位置在Ok.之上而非下面,但是)(如果想实现题目要求,可以在bochs中的/etc/rc文件的最后添加一行调用函数的getjiffies,而不是在main.c中调用,就可以了)
在这里插入图片描述
评测通过

二、在用户程序中使用新增的系统调用

(本题在完成上题的基础上(在虚拟机启动版本0内核时调用一次getjiffies)直接操作,在文章末尾会论述如果直接开始做本题操作有何不同)

(一)初步编写mytest.c文件

根据以下“作业内容”的提示:
在这里插入图片描述
在这里插入图片描述
vscode中打开~/os/linux-0.11-lab文件夹,在b目录下,创建并编辑如下图所示的mytest.c文件(内容并非最终正确答案,为方便演示常见错误,此处为错误代码,正确代码附在最后)
改内容为结合上述提示与上一题main.c相关代码编写
在这里插入图片描述

(二)将mytest.c文件放入bochs虚拟机

注意:可以使用uemacs mytest.c命令直接在虚拟机中创建并编写文件,则可编写完成后可直接进行(三),跳过此节

(注:启动虚拟机后,虚拟机保存启动时的b文件夹的状态,此时物理机中编辑b文件夹下文件,不会对已启动的虚拟机访问的b文件夹下的文件产生影响)
~/os/linux-0.11-lab目录下./run启动
在虚拟机中执行下列命令:

mdir b:mytest.c
mcopy b:mytest.c .

结果如下图所示
在这里插入图片描述

(三)bochs 虚拟机中编译文件

执行下述命令使用gcc编译mytest.c文件

gcc mytest.c -o mytest

出现如下图所示的报错:
参考博文:CSDN-hjjdebug(作者)-ubutu14 下编译linux0.11内核错误记录及解决方法
在这里插入图片描述
进入vscode搜索__attribute__0/linuxincludeunistd.h文件中下图右下划线位置处的__always_inline,而上述gcc的报错提示信息为语法错误,于是现在需要在mytest.c文件中删除掉__always_inline
在这里插入图片描述
使用命令uemacs mytest.c在虚拟机中修改mytest.c文件,删除掉其中的__always_inlinectrl + x+s保存,ctrl + x + ctrl + c退出。
在这里插入图片描述
在这里插入图片描述

再次编译出现新的报错:
在这里插入图片描述
缺少对__NR_getjiffies的定义,而由于上一题中设置的__NR_getjiffies系统调用号为87,需要在mytest.c中添加#define __NR_getjiffies 87

再次使用命令uemacs mytest.c在虚拟机中修改mytest.c文件,添加#define __NR_getjiffies 87ctrl + x+s保存,ctrl + x + ctrl + c退出。
在这里插入图片描述
在这里插入图片描述

mytest.c文件正确代码:

#define __LIBRARY__
#include<unistd.h>
#define __NR_getjiffies 87
_syscall0(long,getjiffies)
void main()
{
	printf("Getjiffies: %ld\n", getjiffies());
}

再次执行gcc编译命令

gcc mytest.c -o mytest
ls

结果如下图所示,编译成功出现可执行文件mytest
在这里插入图片描述

(三)验证mytest文件正确性

在这里插入图片描述

(四)编辑/etc/rc文件

uemacs /ec/rc修改器内容如下图所示。
在这里插入图片描述

验证/etc/rc文件正确性

注意:在虚拟机中执行过命令,未使用相关命令验证就很快退出虚拟机,重启后会发现最近执行的一条或几条命令失效,如uemacs /etc/rc命令修改过/etc/rc文件后,立即退出,再次进入虚拟机发现/etc/rc文件编辑过的内容没有了,正确的做法是在编辑完/etc/rc文件后,执行cat /etc/rc命令,gcc命令类似,需要执行./命令执行gcc编译后的文件

在这里插入图片描述
(得到结果与上图所示打印结果不同也没有关系,共有三条就可以)
注意:重启后得到了如上图所示的输出有可能依然会报错,这可能时题目本身的问题,可以尝试多次执行下列操作:
“进入~/os/linux-0.11-lab/0/linux
执行下列命令:”

make clean;make
cd ../..
./run

注意如果并非做完上一题直接做本题,即在0/linux/init/main.c中没有打印字符串"Getjiffies: %ld", getjiffies(),那么此处/etc/rc文件应该修改为如下图所示内容:

在这里插入图片描述
即本题共需要在系统启动时调用三次getjiffies系统调用。
重启虚拟机后发现评测结果不对也没有关系,根据上上条注意条目的内容多尝试几次

另外,本题的对getjiffies系统调用中的定义中的long均可换成int,也可以通关。

通过测试

三、第二题——极简版思路

(在未第一题的情况下)

1.在0/include/unistd.h中添加系统调用号和函数调用声明

#define __NR_getjiffies 87
long getjiffies(void);

2.将0/kernel/system.h文件中的nr_system_calls = 86改为nr_system_calls = 88

3.在0/include/linux/sys.h文件中添加extern long sys_getjiffies();并在该文件中的sys_call_table[]数组的末尾添加, sys_getjiffies

4.在0/kernel/sched.c文件中添加如下函数

long sys_getjiffies(void)
{
	return jiffies;
}

5.启动虚拟机输入uemacs /etc/rc,在该文件中添加下列内容

cd /usr/root
./mytest
sync
./mytest
./mytest

ctrl+x+s保存,ctrl+x+ctrl+c退出

6.输入uemacs mytest.c在文件中输入如下下内容

#define __LIBRARY__
#include<unistd.h>
#define __NR_getjiffies 87
_syscall0(long,getjiffies)
void main()
{
	printf("Getjiffies: %ld\n", getjiffies());
}

ctrl+x+s保存,ctrl+x+ctrl+c退出

7.gcc mytest.c -o mytest编译生成mytest文件,./mytest验证

在退出虚拟机前要验证

8.退出虚拟机进入0/linux执行几次make clean;make命令(玄学)

9../run进入虚拟机,出现如下图所示的界面,开始评测,评测不成功就在虚拟机里输入几条之前输入过的命令,再次执行第8条(玄学),反复几次,就可以评测通过了

在这里插入图片描述

  • 29
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值