2018-2019-1 20189213《Linux内核原理与分析》第六周作业
系统调用的三层机制(下)
给MenuOS增加time和time_asm命令
首先是删除menu目录,并用git clone重新克隆一个新版本的menu:
进入menu,由于已经提供了一个脚本rootfs,运行make rootfs脚本就可以自动编译并自动生成根文件系统,并同时运行MenuOS系统:
在MenuOS系统中执行已经添加过的time和time-asm命令:
然后我们打开menu目录下的test.c文件,找打定义的time函数和time-asm函数:
在main函数中对这两个函数进行调用:
使用gdb跟踪系统调用内核函数sys_getpid
由于上周做了三个系统调用的C语言实现方法,分别是getuid、getpid、rename,这里我们进行对getpid的跟踪调试:
首先是在test.c中加入getpid:
然后保存test.c,重新make rootfs,发现多了一个getpid的命令:
下面开始进行gdb调试:
先返回LinuxKernel目录,将内核加载进来:
首先在start_kernel函数处设置第一个断点,然后继续执行,到断点处停:
由于getpid是20号系统调用,对应内核处理函数是sys_pid,于是我们在此处也设置断点,然后执行结束:
但此时出现了问题,无法运行到sys_getpid断点处停下。
原因应该是:C库函数getpid()与内核处理函数sys_getpid存在冲突,导致无法运行到sys_getpid!
system_call的代码注释:
注:
(1)sys_call_table(,%eax,4)的理解:因为分派表中的每个表项占4个字节,所以先把系统调用号(eax)乘以4,再加上 sys_call_table 分派表的起始地址,即是所调用的服务例程。
(2)GET_THREAD_INFO 宏用于获得当前进程的thread_info结构的地址,即获取当前进程的信息。
(3)syscall_exit_work 执行了一些进程调度、消息传递的工作,如果进行了进程切换,可能要继续触发新的中断,执行新的系统调用。
system_call流程示意图:
总结
写pid函数时一开始定义函数名为getpid,后来编译发现出错,然后改名为pid,编译成功,估计是函数名getpid与20号系统调用getpid()存在冲突;