深入分析 Linux 内核系统调用

《Linux 内核分析》 MOOC 课程实验 分析 Linux 中断处理过程

在上一周的实验课程中,我们分析了 Linux 内核系统调用过程,理解了中断的概念和中断上下文,掌握了系统调用的原理,今天,我们继续以 Linux 内核 2 号系统调用 fork 函数为例,更加深入的分析系统调用过程。

1.增加 Menu 内核命令行

在这里,我们把上一次实验的 fork 函数以命令行的形式写入内核,在这里我就不赘述操作步骤了,之前的实验有详细的操作流程。

深入分析 Linux 内核系统调用_第1张图片

这就是我们将 fork 函数写入 Menu 系统内核后的效果,通过命令行,实现了操作系统调用过程。

2.GDB 追踪内核调用 sys_fork

通过查询操作系统内核调用函数 API,我们知道 fork 函数的系统调用是 sys_fork,下面我们就通过 GDB 来追踪 sys_fork 的调用过程。同样,这里我也不再赘述操作过程了,之前的实验都有涉及。

深入分析 Linux 内核系统调用_第2张图片

由上图可知, sys_fork 在底层调用的是 do_fork 函数。这里需要注意一下, GDB 支持在 system_call 处设置断点,但却无法让程序停留在这个地方,因此,我们只能暂停在这里了,转向分析源码。

3.分析内核调用汇编源码

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)    #系统调用

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    #恢复现场

irq_return:
    INTERRUPT_RETURN    #中断返回

为了方便阅读,我把上述系统调用源码整理了一下,关键的地方被我打上了注释。总的来说,系统调用过程并不复杂。值得注意的是,在退出系统调用之前,会检查当前进程是否需要执行 syscall_exit_work,如果需要处理,就会查看是否有进程信号或进程调度,若有进程信号或进程调度就再进行相应操作,这不是本次实验的重点,不再展开。据此,我们可以画出从系统调用到中断返回的函数流程图:

深入分析 Linux 内核系统调用_第3张图片

4.总结

本实验通过分析 Linux 内核系统调用源码,深入剖析了系统调用的全过程。通过 int 0x80 中断跳转到系统调用处理程序 system_call 函数处,执行相应的例程。

但是,由于是代表的是用户进程,所以这个执行过程并不属于中断上下文,而是进程上下文。因此,系统调用执行过程中,可以访问用户进程的许多信息,也可以被更高优先级的进程抢占。

当系统调用完成后,把控制权交回到发起调用的用户进程前,内核又会有一次调度。如果发现有优先级更高的进程或当前进程的时间片用完,那么会选择优先级更高的进程或重新选择进程执行。

你可能感兴趣的:(深入分析 Linux 内核系统调用)