张潇月+《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
上周是从用户态来看系统调用,这周是从内核方面来看这个问题。
给MenuOS增加新的系统调用
首先删除当前前的menu,重新克隆一个新版本的menu
Makefile其实就是一个脚本,用make rootfs可以自动编译生成根文件系统,还可以自动启动起来MenuOS
可已很容易的看到我们的MenuOS里增加了我们上节课用的time和time-asm
使用gdb跟踪系统调用
首先回到LinuxKernel
cd.. #返回上一级
用大小S来调试
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
水平分割一下,启动gdb。把3.18的内核带的符号表加载进来。我们连接到我们需要调试的MenuOS里。在start_kernel设置断点,按c会发现,运行在start_kernel那里停止
list可以查看start_kernel这段代码
在time设立设置断点。b sys_time
如果我们执行time命令的话,会停在sys_time这个位置
输入list可以查看内部代码,如果这里一直按s开单步执行,后面一直按n会进入schedule函数。
sys_time返回后进入汇编代码处理gdb无法继续追踪。
系统调用在内核代码中的工作机制和初始化
tips:进程调度的时机对于我们理解系统的运行十分关键
系统调用的初始化:
trap_init()里边有个set_system_trap_gate和system_call,系统调用的中断向量和system_call汇编代码的入口
这之后一旦执行int 0x80 CPU就直接跳转到system_call的位置来执行,就是kernel、entry_32.s
ENTRY(system_call)这个指令就是执行int 0x80后的下一条指令。这一段代码就是系统调用的执行过程,也是中断的过程,也存在保护现场和恢复现场。
sys_call_table就是系统调用定义的系统调用表,eax寄存器用来传递系统调用号;
syscall_after_call需要先保存返回值,在退出之前,如果没有syscall_exit_work,就restore_all就返回用户态;如果有就执行work_pending,其中包含work_notifysig,是处理信号的;work_resched,是处理重新调度的,如果需要就call schedule,jump跳出返回系统调用。
流程图