2021-2022-1 20212818《Linux内核原理与分析》第六周作业
一、实验内容
分析system_call中断处理过程:
- 使用 gdb 跟踪分析一个系统调用内核函数(您上周选择的那一个系统调用),系统调用列表参见 torvalds/linux。推荐在实验楼 Linux 虚拟机环境下完成实验。
- 根据本周所学知识分析系统调用的过程,从 system_call 开始到 iret 结束之间的整个过程,并画出简要准确的流程图
二、实验步骤
1、克隆menu(注意在LinuxKernel内进行操作)
- rm -rf menu //强制删除当前menu
- git clone git://github.com/mengning/menu.git //重新克隆新版本的menu
- cd menu
- 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函数的流程也理解地更加透彻。
并学会了调试内核函数的方法:
- qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
- gdb
- (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
- (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
- (gdb)break start_kernel # 断点的设置,注意寻找对应的系统调用函数名字,例如time命令对应sys_time