【精通内核】EFLAGS寄存器中断控制原理

605 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

前言

📫作者简介小明java问道之路,专注于研究 Java/ Liunx内核/ C++及汇编/计算机底层原理/源码,就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。

📫热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长

🏆InfoQ签约作者、CSDN专家博主/后端领域优质创作者/内容合伙人、阿里云专家/签约博主、51CTO专家🏆

🔥如果此文还不错的话,还请👍关注 、点赞 、收藏三连支持👍一下博主~


本文导读

CPU 对于任务切换是通过时钟中断来控制的,只要我们将中断屏蔽,就可以保证在当前CPU中的所有操作都不会被中断,从而保证了原子性。在单核CPU上, 通过操作 EFLAGS 寄存器相当于保存EFLAGS表示中断。

一、EFLAGS寄存器

与中断相关的操作也仅仅只是上面这些了,是不是是很简单,但是我们还是忽略了一个东西,那就是EFLAGS寄存器,这到底是是个什么东西呢?

EFLAGS寄存器包含了一组状态标志、控制标志、系统标志的寄存器。处理器在初始化时将其初始

化为00000002H。1、3、5、15和 22~31保留未使用。 当然,这里不能依赖这些保留未使用的状态位。

二、EFLAGS寄存器图解

EFLAGS寄存器的详细描述如下图所示

S代表状态标志;C代表控制标志;X代表系统标志;

其中,状态标志有6个;控制标志有1个;系统标志有10个。

一些标志位可以通过特殊的汇编指令来修改,但是这些可被修改的汇编指令都不能直接对这个寄存器进行操作,只能间接设置。例如,可以通过LAHF、SAHF、PUSHFD、POPF、POPFD 这些指令来从 EAX 寄存器或者栈中加载或者存标志位

上面的带L就是LOAD,带S的就是STORE。

当通过寄存器或者栈保存好之前的状态位后,就可以通过位操作指令BT(位测试)、BTS(位测试并设置值)、BTR(位测试并复位值)、BTC(位测试并取反)来检测或者设置状态值。

当挂起一个任务时,CPU 将会自动保存EFLAGS寄存器的内容到任务状态段即 TSS中,下一次在调度任务时再恢复。当然不止有任务切换时会这样做,当我们任务在进行中断或者异常处理时也会保存EFLAGS 寄存器的值。

三、EFLAGS寄存器状态标志位

状态标志位,即 0、2、4、6、7、11 标明了 ADD、SUB、MUL、DIV等算术逻辑运算指令的操作结果。

四、EFLAGS寄存器控制标志位

控制标志位,只有一个DF标志。

这个方向标志(位于EFLAGS寄存器的第10位)控制串指令(MOVS、 CMPS、SCAS、LODS 和STOS)。设置DF 标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。STD 和 CLD 指令分别用于设置和清除DF标志。

五、EFLAGS寄存器系统标志位

EFLAGS寄存器中的系统标志位部分标志位用于控制操作系统或执行操作,它们不允许被应用程序所修改。

总结

CPU 对于任务切换是通过时钟中断来控制的,只要我们将中断屏蔽,就可以保证在当前CPU中的所有操作都不会被中断,从而保证了原子性。在单核CPU上, 通过操作 EFLAGS 寄存器相当于保存EFLAGS表示中断。