zoukankan      html  css  js  c++  java
  • linux内核分析第五周分析system_call中断处理过程

    本实验目的:通过以一个简单的menu小程序,跟踪系统调用的过程,分析与总结系统调用的机制和三层进入的过程。

    实验原理系统调用处理过程与中断处理的机制

    系统调用是通过软中断指令 INT 0x80 实现的,而这条INT 0x80指令就被封装在C库的函数中。(软中断和我们常说的硬中断不同之处在于,软中断是由指令触发的,而不是由硬件外设引起的。)INT 0x80 这条指令的执行会让系统跳转到一个预设的内核空间地址,它指向系统调用处理程序,即system_call函数。

    system_call函数是怎么找到具体的系统调用服务例程的呢?通过系统调用号查找系统调用表sys_call_table!软中断指令INT 0x80执行时,系统调用号会被放入 eax 寄存器中,system_call函数可以读取eax寄存器获取,然后将其乘以4,生成偏移地址,然后以sys_call_table为基址,基址加上偏移地址,就可以得到具体的系统调用服务例程的地址了!然后就到了系统调用服务例程了。需要说明的是,系统调用服务例程只会从堆栈里获取参数,所以在system_call执行前,会先将参数存放在寄存器中,system_call执行时会首先将这些寄存器压入堆栈。system_call退出后,用户可以从寄存器中获得(被修改过的)参数。

    实验步骤:

    1.使用gdb在sys_time处设置断点并list找到的代码

    2.用s(step)跟踪断点

    3.当进入system_call的时候gdb无法继续跟踪,实验结束,找到源代码进行分析

    二、system_call对应的汇编代码的工作过程

    1.库函数触发中断,并给出系统调用号;2.操作系统通过中断描述符表找到对应的中断处理函数:

           于是我们看到了 : ENTRY(system_call)

            进一步找到对应的宏定义:/linux-3.18.6/include/linux/linkage.h

            #define ENTRY(name) \
                                                    .globl name ASM_NL \
                                                    ALIGN ASM_NL \

                                                    name:

          ENTRY(system_call)

     

    RING0_INT_FRAME         # can't unwind into user space anyway
        ASM_CLAC
        pushl_cfi %eax          # save orig_eax
        SAVE_ALL            # 保存现场
        GET_THREAD_INFO(%ebp)
                        # system call tracing in operation / emulation
        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 + 4 * %eax即为系统调用的地址
    syscall_after_call:
        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
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testl $_TIF_ALLWORK_MASK, %ecx  # current->work
        jne syscall_exit_work
     
    restore_all:
        TRACE_IRQS_IRET
    restore_all_notrace:
    #ifdef CONFIG_X86_ESPFIX32
        movl PT_EFLAGS(%esp), %eax  # mix EFLAGS, SS and CS
        # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
        # are returning to the kernel.
        # See comments in process.c:copy_thread() for details.
        movb PT_OLDSS(%esp), %ah
        movb PT_CS(%esp), %al
        andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
        cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
        CFI_REMEMBER_STATE
        je ldt_ss           # returning to user-space with LDT SS
    #endif
    restore_nocheck:
        RESTORE_REGS 4          # skip orig_eax/error_code
    irq_return:
        INTERRUPT_RETURN
  • 相关阅读:
    A/B-test
    LDA概率主题模型
    减肥经验帖
    wide and deep
    利用责任链模式设计一个拦截器
    分享几个 SpringBoot 实用的小技巧
    「造个轮子」——cicada 设计一个配置模块
    「造个轮子」——cicada 源码分析
    「造个轮子」——cicada(轻量级 WEB 框架)
    强如 Disruptor 也发生内存溢出?
  • 原文地址:https://www.cnblogs.com/baka/p/5322850.html
Copyright © 2011-2022 走看看