WHCSRL 技术网

2021-2022-1 20212818《Linux内核原理与分析》第六周作业

一、实验内容

分析system_call中断处理过程:

  • 使用 gdb 跟踪分析一个系统调用内核函数(您上周选择的那一个系统调用),系统调用列表参见 torvalds/linux。推荐在实验楼 Linux 虚拟机环境下完成实验。
  • 根据本周所学知识分析系统调用的过程,从 system_call 开始到 iret 结束之间的整个过程,并画出简要准确的流程图

二、实验步骤

1、克隆menu(注意在LinuxKernel内进行操作)

  1. rm -rf menu //强制删除当前menu
  2. git clone git://github.com/mengning/menu.git //重新克隆新版本的menu
  3. cd menu
  4. ls

实验运行界面如下图:

 2、打开test.c并在其中添加上次实验使用的gitpid的c函数以及汇编代码,使用如下指令打开test.c文件

vim test.c

 然后在test.c中添加函数Getpid和GetPidAsm: 

 

 在main函数中加入两条MenuConfig语句

 3、然后在命令行输入如下指令

make rootfs

 

4、在QEMU对话框中输入help,可以看到qemu中增加了先前我们添加的命令

 

 5、执行新增加的命令getpid和getpid_asm

5、使用gdb跟踪分析一个系统调用内核函数,并在start_kernel处设置断点,输入命令c继续执行,执行过程和在QEMU中的结果如下图:

 6、查看所选用的系统调用函数

 7、继续在sys_getpid处设置断点,发现执行命令getpid时并没有停下,却在执行getpid_asm时停下了

8、进行若干次单步执行,发现出现了进程调度函数,并返回了进程调度函数中的一个当前进程任务的值

9、在system_call处设置断点,程序执行到system_call时会停止,当继续执行时,刚才停下的getpid_asm返回值。

 三、分析系统调用函数

 1、系统调用在内核代码中的工作机制和初始化

        a、main.c中的start_kernel函数调用trap_init函数,trap_init函数调用set_system_trap_gate函数,set_system_trap_gate(SYSCALL_VECTOR,&system_call)函数绑定了中断向量0x80和system_call中断服务程序入口之后,一旦执行int 0x80,cpu就直接跳转到system_call这个位置来执行。

        b、SYSCALL_VECTOR:系统调用的中断向量

2.系统调用是一个特殊的中断

        a、SAVE_ALL:保存现场

        b、call *sys_call_table(,%%eax,4)调用了系统调度处理函数,eax存的是系统调用号,是实际的系统调度程序

        c、sys_call_table:系统调用分派表,syscall_after_all:保存返回值

        d、若有sys_exit_work,则进入sys_exit_work:会有一个进程调度时机。work_pending -> work_notifysig,用来处理信号 可能call schedule:进程调度代码可能跳转到restore_all,恢复现场。

        e、若无sys_exit_work,就执行restore_all恢复,返回用户态INTERRUPT_RETURN <=> iret,结束。

system_call的流程示意图如下所示: 

四、实验总结

        通过这次实验,我对系统调用函数的调用过程更加熟悉,更加理解其原理,对system_call函数的流程也理解地更加透彻。

        并学会了调试内核函数的方法:

  1. qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
  2. gdb
  3. (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
  4. (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
  5. (gdb)break start_kernel # 断点的设置,注意寻找对应的系统调用函数名字,例如time命令对应sys_time

推荐阅读