在用户空间发生中断时,上下文切换的过程

先引用一篇博文,再总结一下相关问题。

所谓上下文切换,实质就是寄存器堆的切换过程。这其中一部分需要硬件来切换,一部分需要软件来处理。

当在用户空间发生中断时,首先由 x86 CPU 从硬件角度进行处理,然后才是 linux 内核的处理。当中断处理完毕,返回到用户空间时,最后的步骤也是交给 CPU 硬件来处理的。

1、  X86 CPU 对中断的硬件支持

CPU 从中断控制器取得中断向量

根据中断向量从 IDT 中找到对应的中断门

根据中断门,找到中断处理程序

在进入中断处理程序前,需要将堆栈切换到内核堆栈。也就是将 TSS 中的 SS0、ESP0装入SS、ESP

然后将原来的用户空间堆栈(SS, ESP)、EFLAGS、返回地址(CS, EIP)压入新的堆栈。

 以上这一系列动作都由硬件完成

 最后,才进入中断处理程序,接下来,由 linux 内核处理

 2、  Linux 内核对中断的处理

保存中断来源号

调用 SAVE_ALL,保存各种寄存器

将 DS、ES 指向  __KERNEL_DS

将返回地址 ret_from_intr入栈

调用 do_IRQ进行中断处理

中断处理完毕,返回到 ret_from_intr

3、 ret_from_intr

所有的中断处理程序在处理完之后都要走到这里;

判断进入中断前是用户空间还是系统空间

如果进入中断前是系统空间,则直接调用  RESTORE_ALL

如果进入中断前是用户空间,则可能需要进行一次调度;如果不调度,则可能有信号需要处理;最后,还是走到 RESTORE_ALL

RESOTRE_ALL 和 SAVE_ALL 是相反的操作,将堆栈中的寄存器恢复

最后,调用 iret 指令 ,将处理权交给 CPU

4、  iret 指令使 CPU 从中断返回

此时,系统空间的堆栈和CPU在第1步处理完之后,交给 linux 内核时的情形是一样的,也就是保存着用户空间的返回地址(CS、EIP)、EFLAGS、用户空间的堆栈(SS、ESP)。

CPU将 CS、EIP、EFLAGS 、SS、ESP恢复,从而返回到用户空间。

 

总结一下:

一个CPU同一时刻只能在用户空间和内核空间的一个中运行。在CPU运行在用户空间的过程中,可能以以下两种方式陷入内核 1)系统调用:这其实是一种同步中断,也称“软件中断”(注意,不是软中断),或者称为“异常”,通过int指令来实现;陷入内核后,内核代码运行在进程上下文中。2)中断(也称异步中断),是由I/O设备产生的中断,它会触发中断服务例程的执行,并往往伴随着软中断的执行,此时,CPU运行在中断上下文中。上文中描述了CPU从中断返回用户空间的过程。

当内核即将返回用户空间时,内核会检查need_resched是否设置,如果设置,则调用schedule(),此时,发生用户抢占。一般来说,用户抢占发生几下情况:
(1)从系统调用返回用户空间;
(2)从中断(异常)处理程序返回用户空间。

与用户抢占相对应的是内核抢占,在内核2.6版本以前并不支持内核抢占,现在我们用的默认一般都是抢占式内核,这可以通过编译时设定编译选项来选择是否使用抢占式内核。对于非内核抢占系统,内核代码可以一直执行,直到完成,也就是说当进程处于内核态时,是不能被抢占的。而对于抢占式内核,在硬中断返回,软中断重新使能,解锁函数,以及开启了内核抢占的系统调用中等一系列情况下都可能发生抢占和CPU的重新调度。


http://www.cnblogs.com/woainilsr/p/3209065.html

### 中断上下文切换的概念及其实现方式 #### 中断的定义与实现 中断是一种机制,允许外部设备或内部事件打断处理器正在执行的任务,并请求操作系统处理这些事件。当发生中断时,CPU会暂停当前任务并转向特定的服务程序(即中断服务例程 ISR),完成后再返回原任务继续执行[^3]。 在硬件层面,中断通常通过触发 CPU 的中断引脚来激活。一旦检测到中断信号,CPU 会自动保存当前的状态信息(如寄存器值、程序计数器 PC 和标志位等)至堆栈中,以便稍后恢复。随后,根据中断向量表定位对应的 ISR 地址并跳转执行[^2]。 #### 上下文切换的概述 上下文切换是指从一个任务切换到另一个任务的过程,在此过程中需要保存即将被替换任务的状态(称为旧上下文),并将目标任务的状态加载回 CPU 寄存器和其他控制单元中(称为新上下文)。这种切换可以发生在多个层次上,包括但不限于 CPU 层次上的寄存器切换以及更高层面上的操作系统级别进程/线程管理[^4]。 对于 **CPU 上下文切换** 来说,主要是涉及通用目的寄存器组、浮点运算单元 FPU 状态以及其他特殊用途寄存器等内容;而对于 **进程上下文切换** 或者说是更广义范围内的 “任务间转换”,则除了上述提到过的那些低级资源外还需要额外关注内存映射表 MMU 设置变化情况等因素影响下的虚拟地址空间重新配置等问题[^1]。 ##### 实际过程描述如下: - 首先,将当前运行进程中所有的必要数据结构副本存储下来——这一步骤可能涉及到用户模式栈指针 ESP 及其关联变量列表项等等; - 接着更新调度队列以反映新的优先级顺序或者时间片耗尽等原因导致的选择结果; - 最终把选中的下一个待执行实体的相关参数装载上去覆盖掉原来的位置从而正式开启新一轮循环周期直到再次遇到类似的场景为止[^2]。 #### 进程上下文切换 vs 线程上下文切换的区别 尽管两者都属于同一类别的概念范畴之内,但由于它们各自所属对象的不同特性决定了二者之间存在显著差异: - 对于单个应用程序而言如果它包含了若干独立工作的子组件形式呈现出来的话我们称之为多线程应用此时在线程间的快速交替操作往往只需要改变少量共享区域之外的部分即可达成高效的目的因为大多数时候它们共用相同的代码段和全局变量集合所以开销相对较小一些。 - 而相比之下不同进程之间的完全隔离性质使得每次都需要进行全面彻底的信息交换工作不仅限于前面提及的基础要素还包括文件句柄数组拷贝等一系列复杂动作因此整体效率较低而且消耗更多的系统资源[^2]。 ```python def context_switch(old_task, new_task): """ Simulate a basic context switching process between two tasks. Args: old_task (dict): The state of the task being switched out. new_task (dict): The state to be loaded into registers for execution. Returns: dict: Updated system state after performing the switch. """ # Save current register values and other relevant states from `old_task`. saved_state = save_registers_and_context(old_task) # Load necessary information about `new_task` back into hardware resources. load_new_task_into_cpu(new_task) return {"current_running": new_task["id"], "saved_states": [saved_state]} ``` 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值