系统调用简单分析

| 2009年4月25日

#define CFI_STARTPROC           .cfi_startproc	//用在每个函数的开始,用于初始化一些内部数据结构
#define CFI_ENDPROC             .cfi_endproc	//在函数结束的时候使用与.cfi_startproc相配套使用
#define CFI_DEF_CFA             .cfi_def_cfa		//定义计算CFA的规则
#define CFI_DEF_CFA_REGISTER    .cfi_def_cfa_register	//xx reg ,offset reg中的值保存在offset中,offset是CFA的
#define CFI_DEF_CFA_OFFSET      .cfi_def_cfa_offset		//xx offset 修改计算CFA的规则,reg中的值不发生变化,之改变offset
#define CFI_ADJUST_CFA_OFFSET   .cfi_adjust_cfa_offset	//与上面相似但是修改前面一个offset
#define CFI_OFFSET              .cfi_offset				//xx reg ,offset reg中的值保存在offset中,offset是CFA的
#define CFI_REL_OFFSET          .cfi_rel_offset
#define CFI_REGISTER            .cfi_register
#define CFI_RESTORE             .cfi_restore
#define CFI_REMEMBER_STATE      .cfi_remember_state
#define CFI_RESTORE_STATE       .cfi_restore_state
#define CFI_UNDEFINED           .cfi_undefined

.macro RING0_INT_FRAME                                                                          
        CFI_STARTPROC simple
        CFI_SIGNAL_FRAME
        CFI_DEF_CFA esp, 3*4
        /*CFI_OFFSET cs, -2*4;*/
        CFI_OFFSET eip, -3*4
.endm

        # system call handler stub
ENTRY(system_call)
        RING0_INT_FRAME                 # can't unwind into user space anyway
        pushl %eax                      # save orig_eax //保存原来的eax中的值
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL					//保存系统寄存器信息
        GET_THREAD_INFO(%ebp)		//获取thread_info结构的地址
                                        # system call tracing in operation / emulation
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)	//检测thread_info中的相关标志看是否有系统跟踪
        jnz syscall_trace_entry		//有系统跟踪则先执行系统跟踪的代码,然后转跳回来(这在syscall_trace_entry中有写的)
        cmpl $(nr_syscalls), %eax		//比较请求的系统调用号和最大系统调用号(验证系统调用号是否有效)
        jae syscall_badsys			//如果请求系统调用号无效则退出
syscall_call:                                                                                   
        call *sys_call_table(,%eax,4)	//跳转到系统调用表中,系统调用表是4字节对齐。
        movl %eax,PT_EAX(%esp)          # store the return value
syscall_exit:
        LOCKDEP_SYS_EXIT			//用于调试使用,只有在开启调试的时候才会去检测系统调用深度
        DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
					//#define ENABLE_INTERRUPTS(x)    sti
					//#define DISABLE_INTERRUPTS(x)   cli  
        TRACE_IRQS_OFF	//关闭中断跟踪
        movl TI_flags(%ebp), %ecx	//
        testl $_TIF_ALLWORK_MASK, %ecx  # current->work //检测是否可以返回用户空间
        jne syscall_exit_work	

syscall_exit_work:
        testl $_TIF_WORK_SYSCALL_EXIT, %ecx                                                     
        jz work_pending
        TRACE_IRQS_ON		//开启系统中断跟踪
        ENABLE_INTERRUPTS(CLBR_ANY)     # could let syscall_trace_leave() call
                                        # schedule() instead
					//允许中断
        movl %esp, %eax
        call syscall_trace_leave
        jmp resume_userspace
END(syscall_exit_work)
看完本文有收获?请分享给更多人

关注「黑光技术」,关注大数据+微服务