网易公开课《Linux内核分析》学习心得-分析system_call中断处理过程

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

实验

本周的实验是跟踪系统调用,所以使用上周的getuid函数。
在test.c内写入GetUid和GetUidAsm。
这里写图片描述
和MenuConfig
这里写图片描述
make并运行MenuOS,用gdb设置断点start_kernel
这里写图片描述
设置断点sys_getuid
这里写图片描述
并一步步运行
这里写图片描述
这里写图片描述
这里写图片描述

system_call过程分析

根据伪代码,画出如下流程图
流程图
接下来分析一下伪代码

.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    #如果当前系统有一些信号需要调用则跳转到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   #跳转到work_pending:
END(syscall_exit_work)
work_pending:
    testb $_TIF_NEED_RESCHED, %cl
    jz work_notifysig #处理信号
work_resched: #重新调度
    call schedule    #调度完成后再call schedule
    jz restore_all    #在跳转到restore_all,返回系统调用
work_notifysig: #信号处理
    ...                  ; deal with pending signals
END(work_pending)

可以看到无论是中断返回(ret_from_intr) ,还是系统调用返回,都使用了 work_pending 和resume_userspace。

对于宏SAVE_ALL来说,这条语句会把将寄存器的值压入堆栈当中,压入堆栈的顺序对应struct pt_regs ,出栈时,这些值传递到struct pt_regs的成员,实现从汇编代码向C程序传递参数。struct pt_regs可以在arch/x86/include/asm/ptrace.h中查看。

总结

当用户态的进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。因为内核实现了很多不同的系统调用,因此进程必须传递一个名为系统调用号的参数来识别所需的系统调用。
系统调用处理程序与其他异常处理程序的结构类似,执行下列操作:
1、在内核态栈中保存大多数寄存器的内容
2、代用系统调用服务例程的对应C函数来处理系统调用
3、退出系统调用程序:用保存在内核栈中的值加载寄存器,CPU从内核态切换回用户态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值