分析system_call中断处理过程

初始化的时候会将0x80和system_call绑定起来
system_call伪代码

分析system_call中断处理过程_第1张图片

进程调度的时机对于分析很关键
系统调用机制的初始化

分析system_call中断处理过程_第2张图片

系统调用初始化从trap_init();开始
用到了set_system_trap_gate函数,其中涉及到了系统调用的中断向量和system_call汇编代码的入口,被声明成了一个函数,将其绑定起来
一旦执行0x80,cpy自动跳转到system_call来执行

系统调用机制初始化之后,则开始执行system_call

system_call的代码在entry_32.S文件中
从ENTRY(system_call)开始

分析system_call中断处理过程_第3张图片

系统调用其实是一个特殊点的中断,存在保护和恢复现场
SAVE_ALL来保护现场
sys_call_table传递来了系统调用号
syscall_after_call需要保存返回值

在退出之前还需要做syscall_exit_work
然后restore_all来恢复现场
简化后的汇编代码:

.macro INTERRUPT_RETURN  
    iret
.endm
.macro SAVE_ALL        
    ...
.macro RESTORE_INT_REGS
    ...
.endm

ENTRY(system_call)
    SAVE_ALL
syscall_call:
    call *sys_call_table(,%eax,4)
    movl %eax, PT_EAX(%esp)  ; store the return value
syscall exit:
    testl $_TIF_ALLWORK_MASK, %ecx # current->work
    jne syscall_exit_work
restore_all:
    RESTORE_INT_REGS
irq_return:
    INTERRUPT_RETURN      
ENDPROC(system_call)

syscall_exit_work:
    testl  $_TIF_WORK_SYSCALL_EXIT, %ecx
    jz work_pending
END(syscall_exit_work)

work_pending:
    testb $_TIF_NEED_RESCHED, %cl
    jz work_notifysig
work_resched:
    call schedule
    jz restore_all
work_notifysig:
    ...                  ; deal with pending signals
END(work_pending)

进入system_call后
syscall_call查询系统调用对应的的处理函数
syscall_exit判断当前任务是否需要处理,需要处理的则跳转去处理
restore_all恢复现场
irq_return结束中断
syscall_exit_work处理任务跳转至work_pending
work_pending跳转至work_notifysig
work_resched需要重新调度的话在调度完成后跳转至restore_all返回系统调用
work_notifysig处理信号

流程图如下


总结:在中断处理过程中,首先要保存现场,然后接受中断并处理中断任务,处理任务结束后,恢复现场

在系统调用返回前,有可能发生进程调度call schedule
在当前进程有可能产生进程间通讯的信号则需要去处理

王潇洋
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

你可能感兴趣的:(分析system_call中断处理过程)