作业信息
这个作业属于哪个课程 | <2020-2021-1Linux内核原理与分析)> |
---|---|
这个作业要求在哪里 | <2020-2021-1Linux内核原理与分析第六周作业> |
这个作业的目标 | <给MenuxOS增加命令、使用gdb跟踪系统调用内核函数、分析system_call处理过程> |
作业正文 | < https://i.cnblogs.com/posts/edit> |
一、实验楼实验
本周内容围绕系统调用system_call的处理过程,在MenuOS中运行getpid命令,通过gdb跟踪调用time函数的过程,并分析system_call代码对应的工作过程。
二、实验过程
在MenuOS中运行getpid命令
进入LinuxKernel目录,删除menu目录,然后从github上克隆一个menu。该版本中已经写了time和time_asm两个系统调用
cd ~/LinuxKernel //强制删除当前menu目录
rm -rf menu // 重新克隆一个新的menu
git clone https://github.com/mengning/menu.git
cd menu //打开menu目录
make rootfs //自动编译
进入menu目录,运行make rootfs对menu内文件进行编译,打开MenuOS输入help查询系统调用函数如下所示
在menu目录中找到test.c文件打开,写入getPid()方法调用系统调用,避免函数名与系统调用函数getpid()重复。
由于test.c种通过MenuConfig()定义了调用函数名,在MenuOS中直接输入pid可以调用,获得当前进程为1,该进程也叫根进程。它负责产生其他所有用户进程。所有的进程都会被挂在这个进程下。
gdb跟踪调用time函数的过程
退回LinuxKernel目录,shift+ctrl+o切换横屏,然后在终端1执行如下命令:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
在终端2打开gdb,在start_kernel设置断点,执行如下命令:
gdb
file linux-3.18.6/vmlinux
target remote:1234
b start_kernel
MenuOS在start_kernel处暂停,继续执行后面的程序,在sys_time函数中设置断点,在MenuOS中输入time后执行gdb,执行情况如下:
b sys-time
sys_time函数执行至SYSCALL_DEFINE1处,调用list,可以显示当前断点附近代码内容:
对sys_time函数进行跟踪,最终显示系统时间:
system_call代码对应的工作过程分析
在system_call处设置断点,但是gdb不支持单步跟踪,MenuOS中仍停留在sys_time这个位置:
编辑linux-3.18.6/arch/x86/kernel/entry_32.S,查看system_call函数代码:
原因是system_call不是一个正常的函数,只是一段汇编代码的起点,内部没有严格遵守函数调用堆栈基址,不支持gdb一条一条的调试。
分析system_call代码,系统调用的流程大致为:
三、学习总结
本周主要学习了Linux内核系统调用的过程,并通过gdb和代码分析了调用过程。一般情况下,在用户态调用time()函数时,实际上调用了系统函数sys_time(),而用户态中有一个系统调用库函数xyz(),里面通过中断向量0x80触发system_call中断服务程序入口这段汇编代码,由用户态切换到内核态。首先通过SAVE_ALL保护现场,然后通过system_call函数中调用分配表找到系统调用内核处理函数指针,调用函数后通过restore_all和INTERRUPT_RETURN(iret)恢复现场并返回系统调用到用户态结束。以上system_call调用为软中断,和其他所有中断类似,可以推广到一般的中断处理过程。