2020-2021-1 20209302毕慧敏 《Linux内核原理与分析》第六周作业

作业信息

这个作业属于哪个课程 <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调用为软中断,和其他所有中断类似,可以推广到一般的中断处理过程。

posted @ 2020-11-15 21:39  20209302毕慧敏  阅读(95)  评论(0编辑  收藏  举报