OS实验2-6 课后作业2.3:系统调用
第1关:版本1内核执行的完整系统调用序列
本关任务:
解题过程:
1.跟踪到系统调用发生
同实验2-5
2.跳过 0 号进程发出的连续多个 pause 系统调用
设置一个新断点,将0号进程的pause系统调用排除在外
先关闭此断点,运行至0号进程pause调用时,打开此断点,关闭原断点
第2关:在版本1中输出系统调用信息
本关任务:
解题过程:
1.跟踪到系统调用发生
找到系统调用函数system_call,发现其是汇编语言函数,检查其调用函数情况
发现其调用了c函数do_signal,do_signal在signal.c中定义,故在signal.c中添加输出字符函数myfunc(其实在任何一个c文件中添加此函数均可)
2.编写输出调用号和进程号函数myfunc
定义变量保留上一次输出的进程号和系统调用号,在这一次输出时进行比对
由于pid变量不在fork.c中,故采用sys_getpid的方式获取当前进程号
3.在system_call中调用myfunc
找到一条调用系统调用表的汇编指令
可知此时%eax存放的是系统调用号
注意:题目中给出的pushl $eax有误,应该是pushl %eax
最后记得对修改后的内核文件重新编译
第3关:在版本0中输出系统调用信息
本关任务:
解题过程:
类似第2关,首先找到system_call函数
其次编写输出函数myfunc
在system_call函数中调用
第4关:为版本0内核增加一个系统调用getjiffies
本关任务:
解题过程:
1.增加新的系统调用
题目要增加一个“系统调用”,前几关在任意c文件中添加函数方法不再起作用,应找到专门定义系统调用的文件sys.c后在其中添加
查看sys.c文件,选择一个函数,搜索其定义信息
发现其在sys.c、sys.h、unistd.h中都有相关定义,按图索骥修改之
查看jiffies为long类型,故在sys.c中定义如下
在sys.h中增加相关定义
在unistd.h中增加相应的系统调用号
在 nr_system_calls文件中修改系统调用总数
2.系统启动时自动调用
在main函数中增加对此系统调用的引用
测评后,发现缺少“对函数的定义”
查看后发现main函数中对一些系统调用进行了always_inline相应添加之,评测通过
补充知识:
- unistd.h这个文件包含了系统调用清单,用来给每个系统调用分配一个唯一的号码。系统调用号的定义格式如下:
#define__NR_nameNNN
其中,name用系统调用名称代替,而NNN是该系统调用对应的号码
- inline attribute((always_inline))的意思是强制内联.所有加 inline attribute((always_inline)) 修饰的函数在被调用的时候不会被编译成函数调用,而是直接扩展到调用函数体内
第5关:在用户程序中使用新增的系统调用
本关任务:
解题过程:
1.编写程序mytest.c
由题中提示知,若想在函数中调用系统调用函数,可以使用 \_syscall0
等宏来定义
main.c中对fork使用_syscall0宏得到定义
这里同样使用_syscall0宏定义getjiffies,同时定义其系统调用号,void函数再调用之
2.将mytest.c放入bochs中
打开bochs,使用mcopy将mytest.c拷入,gcc编译
3.设置开机自动启动
uemacs /etc/rc
使用uemacs命令编写自启动脚本,添加三个./mytest即可
补充知识:
1._syscall0在unistd.h中的内嵌宏代码,它以汇编的形式调用Linux的系统调用的中断 int 80,并在eax寄存器指定系统调用的功能号
2.启动虚拟机后,虚拟机保存启动时的b
文件夹的状态,此时物理机中编辑b
文件夹下文件,不会对已启动的虚拟机访问的b文件夹下的文件产生影响,若想修改必须先关掉虚拟机