2018-2019-1 20189203《linux内核原理与分析》第六周作业

第一部分

  • 给Menu OS增加命令
    输入命令
git clone http://github.com/mengning/menu.git
make rootfs```
- 查看增加的time 和time_asm命令
 ![](https://img2018.cnblogs.com/blog/1504872/201811/1504872-20181118181353017-941660215.png)
![](https://img2018.cnblogs.com/blog/1504872/201811/1504872-20181118181400092-349504569.png)
# 第二部分 实验(使用gdb跟踪调用内核函数)
## 1.操作
我选用的是上周使用的rename,首先编辑menu中的test.c文件,给MenuOS增加rename和rename_asm命令,如图
 ![](https://img2018.cnblogs.com/blog/1504872/201811/1504872-20181118181407466-1147089241.png)
运行可以看到MenuOS中新增两条命令:
 ![](https://img2018.cnblogs.com/blog/1504872/201811/1504872-20181118181414223-761815648.png)
使用gdb跟踪sys_rename,在sys_rename处设置断点,在MenuOS中执行rename命令,停在SyS_rename处,然后单步执行。 
![](https://img2018.cnblogs.com/blog/1504872/201811/1504872-20181118181744253-38164919.png)
## 2.系统调用处理过程分析。
系统调用机制的初始化是在 start_kernel 中的 trap_init()里进行的,如下程序,SYSCALL_VECTOR系统调用的中断向量,&system_call是 system_call的入口,一旦执行int 0x80,CPU就会立即跳转到此处。
``` #ifdef CONFIG_X86_32
   set_system_trap_gate(SYSCALL_VECTOR, &system_call); 
   set_bit(SYSCALL_VECTOR, used_vectors);
#endif

将system_call代码简化并加以分析:

     RING0_INT_FRAME    
     ASM_CLAC        
     pushl_cfi %eax            //保存系统调用号;
     SAVE_ALL                  //将用到的所有CPU寄存器保存到栈中
     GET_THREAD_INFO(%ebp)     //ebp用于存放当前进程thread_info结构的地址
     testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
     jnz syscall_trace_entry
     cmpl $(nr_syscalls), %eax  //检查系统调用号
     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              //恢复现场 
 irq_return:
     INTERRUPT_RETURN             //iret

从entry(system_call)开始看这段代码,根据系统调用号来查sys_call_table表中的位置,调用系统调用对应的系统函数,在syscall_exit里面判断当前的任务是否需要处理syscall_exit_work,进入syscall_exit_work,这是最常见的进程调度时机点。
System_call流程图如下图所示:

如图,流程图中涉及syscall_exit_work内部处理的一些关键点,大致的过程是syscall_exit_work需要跳转到work_pending,里面有work_notifysig处理信号。还有work_resched是需要重新调度的,这里是进程调度的时机点call schedule,调度完后之后就会跳转到restore_all,恢复现场返回系统调用到用户态。

原文地址:https://www.cnblogs.com/23du/p/9978734.html