2020-2021-1 20209320 《Linux内核原理与分析》第六周作业
一.给MenuOS增加命令
(1)先用rm -rf menu强制删除当前menu目录,然后用git clone重新克隆一个新的menu。
(2)用make rootfs打开menu镜像,操作完成后可以看到MenuOS菜单中新增了两个命令
(3)在test.c中加入getpid(),再次使用make rootfs,使用新写入的GPid查看返回的pid值
二.使用gdb跟踪系统调用内核函数sys_time
(1)返回的LinuxKernel目录下,调试内核
(2)新建一个shell使用gdb调试
(gdb)file linux-3.18.6/vmlinux
(gdb)target remote:1234
(gdb)b start_kernel
(3)分析system_call处理过程
ENTRY(system_call)
RINGO_INT_FRAME
ASM_CLAC
push1_cfi %eax /*保存系统调用号*/
SAVE_ALL /*保存现场,将用到的所有CPU寄存器保存到栈中*/
GET_THREAD_INFO(%ebp) /*ebp用于存放当前进程thread_info结构的地址*/
test1 $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmp1 $(nr_syscalls),%eax /*检查系统调用号(系统调用号应小于NR_syscalls)*/
jae syscall_badsys /*不合法,跳入异常处理*/
syscall_call:
call *sys_call_table(,%eax,4) /*合法,对照系统调用号在系统调用表中寻找相应的系统调用的内核处理函数*/
movl %eax,PT_EAX(%esp)/*保存返回值到栈中*/
syscall_exit:
testl $_TIF_ALLWORK_MASK, %ecx/*检查是否需要处理信号*/
jne syscall_exit_work /*需要,进入 syscall_exit_work*/
restore_all:
TRACE_IRQS_IRET /*不需要,执行restore_all恢复,返回用户态*/
irq_return:
INTERRUPT_RETURN /*相当于iret*/
sysytem_call 流程示意图
总结
中断向量0x80对应system_call中断服务程序入口,cpu一旦执行int 0x80,cpu就直接跳转到system_call这个位置来执行。当一个系统调用发生时,进入内核处理这个系统调用,系统调用的内核服务程序在服务结束返回到用户态之前,可能会发生进程调度,在进程调度中会发生进程上下文切换。从系统调用处理进程的入口开始,可以看到SAVE_ALL保存现场,然后找到system_call,sys_call_table,call *sys_call_table(,%eax,4)就是调用了系统调用的内核处理函数,之后restore_all和最后一个INTERRUPT_RETURN(iret)用于恢复现场并返回系统调用到用户态结束。