分析system_call中断处理过程

上周我们使用gcc内嵌汇编调用系统调用,这次我们具体分析下过程。

将getpid嵌入menuos

代码从github下载,步骤如下:

1. 增加一个函数,getpid
2. 在main中添加MenuConfig("getpid","Show Pid", Getpid); 3. 重新编译 make roofs 4. 此时启动 执行getpid就可以看到打印出pid为1

 

menuos的原理

其实这个很简单,在上上周我们分析过linux内核的启动过程,1号进程,就是init,它的执行逻辑是/sbin/bin,所以这里的menuos就是编写的init。

这里注意,linux内核源码不包含/sbin/bin,一般的发行版使用的是FreeBSD的版本。

这里的menuos就是自己制作init,然后嵌入linux内核编译出的镜像。
所以在menuos中执行getpid,得到的pid为1,见上图。

中断处理

中断分为两种,一种是外中断,由外部的IO设备产生,另一种是内中断,也称为异常,由CPU内部产生。

这里涉及到一个很重要的概念,叫做中断上下文。

CPU的运行状态,分为以下三种:

1. 内核态,运行于进程上下文,内核代表进程运行于内核空间。
2. 内核态,运行于中断上下文,内核代表硬件运行于内核空间。 3. 用户态,运行于用户空间。

从上面,我们可以看出,中断上下文不与任何的进程相关联,仅仅运行在内核空间,而且一般只访问内核数据。

这里顺便总结下进程上下文:

1. 用户级上下文: 正文、数据、用户堆栈以及共享存储区; 2. 寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP); 3. 系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。

其实就是包含三个内容:用户数据、硬件状态(主要是寄存器)、内核数据。
所以,当发生进程调度时,要将三个上下文全部进行切换。
当进行系统调用时,仅仅需要切换寄存器上下文。

相比进程上下文,中断上下文仅仅包含一些寄存器的信息。发生中断时,所谓的保护现场和恢复现场,指的就是这些寄存器信息。

分析system_call

代码如下:

# system call handler stub
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) # 获取thread_info结构的信息 # system call tracing in operation / emulation testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) # 测试是否有系统跟踪 jnz syscall_trace_entry # 如果有系统跟踪,先执行,然后再回来 cmpl $(NR_syscalls), %eax # 比较eax中的系统调用号和最大syscall,超过则无效 jae syscall_badsys # 无效的系统调用 直接返回 syscall_call: call *sys_call_table(,%eax,4) # 调用实际的系统调用程序 syscall_after_call: movl %eax,PT_EAX(%esp) # 将系统调用的返回值eax存储在栈中 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 # 检测是否所有工作已完成 jne syscall_exit_work # 未完成,则去执行这些任务 restore_all: TRACE_IRQS_IRET # iret 从系统调用返回

这段代码的逻辑主要就是:

1. 保存寄存器上下文,
2. 检查系统调用号是否合法 3. 执行系统调用 4. 检查是否还有别的工作需要完成 5. 退出系统调用,返回到用户态

我们继续跟踪里面的syscall_exit_work,它用来处理系统调用之后,未完成的工作

syscall_exit_work:testl $_TIF_WORK_SYSCALL_EXIT, %ecx # 测试syscall的工作完成 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)

这一段的主要作用还是进入work_pending

work_pending代码:

work_pending:testb $_TIF_NEED_RESCHED, %cl # 判断是否需要调度 jz work_notifysig # 不需要则跳转到work_notifysig work_resched: call schedule # 调度进程 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 andl $_TIF_WORK_MASK, %ecx # 是否所有工作都已经做完 jz restore_all # 是则退出 testb $_TIF_NEED_RESCHED, %cl # 测试是否需要调度 jnz work_resched # 重新执行调度代码

这段的逻辑很清楚

1. 先检查是否需要调度,
2. 如果是,则进行进程调度,之后再次判断。 3. 如果不需要调度,那么去执行work_notifysig,处理信号

work_notifysig代码:

work_notifysig:              # 投递信号 #ifdef CONFIG_VM86 testl $X86_EFLAGS_VM, PT_EFLAGS(%esp) # 判断8086虚模式,也就是保护模式 movl %esp, %eax jne work_notifysig_v86 # 返回到内核空间 1: #else movl %esp, %eax #endif TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) movb PT_CS(%esp), %bl andb $SEGMENT_RPL_MASK, %bl cmpb $USER_RPL, %bl jb resume_kernel xorl %edx, %edx call do_notify_resume # 将信号投递到进程 jmp resume_userspace # 恢复用户空间 #ifdef CONFIG_VM86 # 如果是VM86模式,需要保存状态信息 ALIGN work_notifysig_v86: pushl_cfi %ecx # save ti_flags for do_notify_resume call save_v86_state # 保存虚模式下的状态 popl_cfi %ecx movl %eax, %esp jmp 1b # 跳转到上面的代码,执行do_notify_resume #endif END(work_pending)

这段代码主要是处理信号:

1. 先检查是否是8086保护模式 2. 如果是,那么需要先保存虚模式下的状态信息 3. 然后跳转到之前的代码继续执行 4. 将信号投递到进程 5. 恢复用户空间

之后就是返回系统调用

流程图总结

如图:

总结

系统调用中断,本质上也是一个保存状态、进行处理、返回并恢复状态的过程。

署名信息

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

 

转载于:https://www.cnblogs.com/jorilee/p/5326670.html

实验5 :分析system_call中断处理过程相关推荐

  1. 分析system_call中断处理过程

    分析system_call中断处理过程 上周我们使用gcc内嵌汇编调用系统调用,这次我们具体分析下过程. 将getpid嵌入menuos 代码从github下载,步骤如下: 1. 增加一个函数,get ...

  2. Linux内核设计第五周学习总结 分析system_call中断处理过程

    陈巧然原创作品 转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 使用gdb跟踪分析一 ...

  3. 5. 简单分析system_call中断处理过程

    ##################################### 作者:张卓 原创作品转载请注明出处:<Linux操作系统分析>MOOC课程 http://www.xuetang ...

  4. 中断处理过程示意图_ucore操作系统实验笔记 - Lab1

    最近一直都在跟清华大学的操作系统课程,这个课程最大的特点是有一系列可以实战的操作系统实验.这些实验总共有8个,我在这里记录实验中的一些心得和总结. Task1 这个Task主要是为了熟悉Makfile ...

  5. Mycat读写分离以及拆库拆表综合实验3:通过日志分析mycat路由过程

    #在客户端查询t1表中id=1的值 我们在之前的schma.cnf中定义了t1在是一张全局表,且位于名称为mysql的分片节点(datanode)上,因此当mycat拦截到客户端SQL语句之后,分析t ...

  6. 华北电力大学计算机图形学实验报告,华北电力大学计算机图形学实验报告分析.doc...

    华北电力大学计算机图形学实验报告分析 科 技 学 院 课程设计(综合实验)报告 ( 2013 -- 2014 年度第 2 学期) 实验名称 OpenGL基本图元绘制实验 课程名称 计算机图形学 | | ...

  7. 中断处理过程示意图_聊聊什么是中断机制?

    什么是中断 中断其实是一种"中断"事件,中断具体代表什么意思需要考虑它所处的上下文环境和参照对象是谁.考虑事件,我们可以简单把中断抽象为这样一种模型: 当我们分析某种中断事件时,我 ...

  8. x86异常处理与中断机制(3)中断处理过程

    上一节讲完了根据中断类型号找中断服务程序的过程,现在着重说明一下更加完整的中断处理过程吧. 本节以8086时代的中断处理过程为例进行说明,主要分两大部分 硬件处理 软件处理 需要注意,这不是绝对的,得 ...

  9. 【人工智能项目】MNIST手写体识别实验及分析

    [人工智能项目]MNIST数据集实验报告 这是之前接的小作业,现在分享出来,给大家以学习!!! [人工智能项目]MNIST手写体识别实验及分析 1.实验内容简述 1.1 实验环境 本实验采用的软硬件实 ...

最新文章

  1. Ubuntu中APUE 3rd中实例编译时err_sys函数找不到解决方法
  2. vue中父子组件先后渲染_VUE如何实现子父组件、父子组件、兄弟组件传值
  3. 单点登录系统(SSO)和Session共享解释
  4. 1.7 对新序列采样-深度学习第五课《序列模型》-Stanford吴恩达教授
  5. Struts2的下载安装
  6. Java是值传递还是引用传递?
  7. 性能测试需求调研分析方法
  8. 年底活动那么多!!给你一组超牛的促销标签素材!!!
  9. QT不让windows休眠的方法
  10. Win11如何添加过时硬件?Win11添加过时硬件的方法
  11. js+面向对象相关笔记(一)
  12. Tensorspace一款神奇的神经网络可视化应用
  13. 【科普】有趣“小学”数学题,做出一道即可成名(持续补充)
  14. 斜齿轮重合度计算公式_斜齿轮的端面重合度计算
  15. 《电子元器件的可靠性》——3.3节可靠性筛选试验
  16. springboot实现条形码_java生成条形码(多种条码类型生成)
  17. C# 写入CSV文件
  18. 计算机人工智能论文参考文献格式,人工智能论文参考文献范例借鉴
  19. IB课程体系的优缺点介绍
  20. ESP32 485光照度

热门文章

  1. K8s系列之:搭建高可用K8s v1.23.5集群详细步骤,3个master节点,3个Node节点
  2. 少用的却实用的计算机知识
  3. springboot+quartz报错:Table ‘XXXX.QRTZ_TRIGGERS‘ doesn‘t exist
  4. 鸿蒙强者排行榜,琉璃美人煞十大强者排名,腾蛇垫底,司凤第七,罗喉计都屈居第二...
  5. 【Docker学习笔记 五】深入理解Docker容器数据卷机制
  6. 基于Maven+SpringMVC+Spring+MyBatis+Layui整合框架,超详细的SSM整合❤️
  7. Ribbons界面介绍(2)——这是不是合适的用户界面
  8. HDU2550 百步穿杨【打印图案】
  9. 【Vue项目】二、去哪儿网APP——首页开发
  10. 颜色混合BlendFunc用法实例总结