李亚健 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验过程:
使用gdb跟踪分析一个系统调用内核函数(上周选择的那一个系统调用)
1.进入实验楼环境,进入LinuxKernel:
rm menu -rf
git clone https://github.com/mengning/menu.git 从github中克隆
cd menu
make rootfs
2.给menuOS增加自己的内容:
<1>在test.c中的main函数里增加MenuConfig
<2>增加对应的a.c函数和a_asm.c函数
<3>make rootfs 自动编译脚本
3.开始调试:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb file linux-3.18.6/vmlinux
gdb target remote:1234
查询4号系统调用,设置断点: b a_asm
gdb c
可以看到:Break point 2,at time.c:63
gdb s
一直按n单步执行会进入schedule函数。
a_asm返回后进入会汇编代码处理的gdb不好追踪。
执行int 0x80执行后system_call对应的代码
gdb b system_call
可以找到entry_32.s,line 477.
二、分析system_call对应的汇编代码的工作过程
1.Trap_init():Set_system_trap_gate Set_bit
2.看老师简化后便于理解的system_call伪代码
3.在entry_32.S 系统调用就是特殊的中断 存在保护和恢复现场
4.SAVE_ALL Sys_call_table就是调用sys_time
5.先保存返回值 Syscall_exit_work 没有则返回到用户态。
6.INTERRUPT_RETURN <=> iret,结束。
字很难看,见谅!
三、对“系统调用处理过程”的理解:
1、用户态进程调用int 0x80(或system_call),中断进程,保护现场,让CPU停止当前工作转为执行系统内核中预设的一些任务,然后进入才能进入内核态;调用结束后 又会恢复现场回到内核态。
2、中断后会对调用的任务进行各种检查,并进行调度,完成调用后,再进行检查,才能执行iret返回。
3、将处理机状态由用户态转为系统态。之后,由硬件和内核程序进行系统调用的一般性处理,即首先保护被中断进程的CPU环境,将处理机状态字PSW、程序计数器PC、系统调用号、用户找指针以及通用寄存器内容等压入堆栈,然后,将用户定义的参数传送到指定的地方保存起來。分析系统调用类型,转入相应的系统调用处理子程序。为使不同的系统调用能方便地转向相应的系统调用处理子程序,在系统中配置了一张系统调用入口表。表中的每个表目都对应一条系统调用,其中包含该系统调用自带参数的数目、系统调用处理子程序的入口地址等。内核可利用系统调用号去查找该表,即可找到相应处理子程序的入口地址而转去执行它。在系统调用处理子程序执行完后,恢复被中断的或设置新进程的CPU现场,然后返冋被中断进程或新进程,继续往下执行