《Linux内核分析》第五周笔记 扒开系统调用的三层皮(下)

扒开系统调用的三层皮(下)

一、给menuOS增加time和time-asm

  通过内核调试系统调用。将上次做的实验加入到menusOS,变成menusOS里面的两个命令。

1 int Getpid(int argc , char * argv[])

2{

3 int pid;

4 pid=getpid();

5 printf("pid=%d\n",pid);

6 return 0;

7 }

8

9 int Getpidasm(int argc , char *argv[])

10 {

11 int pid;

12 asm volatile(

13 "mov $0,%%ebx\n\t"

14 "mov $0x14,%%eax\n\t"

15 "int $0x80\n\t"

16 "mov %%eax, %0\n\t"

17 :"=m"(pid)

18 );

19 printf("pid = %d\n",pid);

20 return 0;

21 }

/*强制删除当前的menuOS*/

/*克隆一个menu*/

/*运行脚本*/

这次的menuOS支持的命令增加,增加了time和time-asm两条命令。

二、使用gdb跟踪系统调用内核函数sys_time

/*13号time对应的内核处理函数sys_time*/

/*启动到menuOS,执行time命令系统调用,停在system time函数的位置*/

 

如果一直按n单步执行会进入schedule函数。

sys_time返回后进入汇编代码处理gdb无法继续跟踪。

执行0x80之后cpu自动跳转到system_call.

三、系统调用在内核代码中的处理过程

1、系统调用在内核代码中的工作机制和初始化

从int 0x80触发一个系统调用到执行系统调用处理的函数sys time,到返回用户态的整个过程是很重要的。进程调度的时机非常关键。

system call系统调用的处理过程:

初始化中断向量的过程中将0x80与system call联系起来。

通过系统调用号将system call与sys_xyz联系起来。

返回用户态之前有一个调度时机,从systime退出后会跟踪到schedule。

系统调用机制的初始化:

2、简化后便于理解的system call伪代码

系统调用是特殊的中断

system call handler stub ENTRY(system_call)              

RING0_INT_FRAME            

ASM_CLAC     pushl_cfi %eax            

SAVE_ALL              /*宏*/    

GET_THREAD_INFO(%ebp)                       

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) /*根据系统调用号查sys_call_table表里的位置,调用处理函数*/

syscall_after_call:                  

movl %eax,PT_EAX(%esp)     

syscall_exit:     LOCKDEP_SYS_EXIT                   

DISABLE_INTERRUPTS(CLBR_ANY)                          

TRACE_IRQS_OFF           

movl TI_flags(%ebp), %ecx     

testl $_TIF_ALLWORK_MASK, %ecx    

jne syscall_exit_work  /*检测当前任务处理jne syscall_exit_work*/

syscall_exit_work: /*如果不处理任务就结束了*/    

testl $_TIF_WORK_SYSCALL_EXIT, %ecx    

jz work_pending     /*处理信号*/    

TRACE_IRQS_ON         

ENABLE_INTERRUPTS(CLBR_ANY)    

movl %esp, %eax    

call syscall_trace_leave    

jmp resume_userspace   /*恢复用户空间 */

END(syscall_exit_work)

work_pending:     testb $_TIF_NEED_RESCHED, %cl    

jz work_notifysig      work_resched:     call schedule     /*重新调度*/    

 

在系统调用返回之前有可能发生进程调度(call schedule)

在当前进程有信号发生进程间通讯他会处理当前进程

进程调度过程中会发生进程上下文切换

将内核抽象成很多个中断处理的集合

3、分析system_call到iret的过程

四、总结

  这次实验我学习到从int 0x80触发一个系统调用到执行系统调用处理的函数sys time,到返回用户态的整个过程。学习到了进程调度的时机非常关键。system call系统调用的处理过程是:初始化中断向量的过程中将0x80与system call联系起来。通过系统调用号将system call与sys_xyz联系起来。返回用户态之前有一个调度时机,从systime退出后会跟踪到schedule。这次课程使我对系统调用的过程有了更深的了解。

posted @ 2016-03-23 20:11  20135132  阅读(191)  评论(0编辑  收藏  举报