为什么我们需要在系统启动或系统初始化时禁用所有中断?

Raj*_*esh 5 assembly kernel interrupt startup

在系统初始化或启动代码级别禁用所有中断需要什么.如果我不禁用中断会发生什么?

cad*_*luk 6

在某些情况下,中断是不需要的,因此它们被禁用.
这些例子很多,但我可以想出这些:

  • 修改 ss:(e)sp.如果触发了中断,flags寄存器将被压入堆栈.无效的堆栈值会将该副本移动到某个随机位置.改变ss:(e)sp不是原子的,至少在x86上,因为它由多个指令组成,因此中断可以在两者之间触发.
    但是,如果正确编写代码,则可以在不禁用中断的情况下实现相同的原子性,因为它们在某些情况下自动禁用.

    @MichaelPetch发表了一些关于8088处理器(8086的"弱兄弟",第一个x86处理器)的专业,描述了这些"特定场合"的例外,在这个答案的评论中:

    关于中断被关闭直到下一条指令结束(移动值之后SS)的情况确实如此,但是有8088个处理器有一个错误,其中中断没有在SS更改后正确关闭.我们这些(恐龙)会经常把CLI/ STI 在周围SS:SP更新以防万一(这样的错误运行8088系统的机会很可能接近零).从历史的角度来看,这篇PC mag文章可能会对这一古老问题有所了解.

    (代码格式化程序已添加.)

  • 缺乏IDT/IVT.保护模式IDT初始化或16位实模式IVT被修改(或归零或其他)时,中断将跳转到某个存储器位置,而不是指令所在的位置.

通常,您可以说以某种非原子方式修改IDT/IVT的操作需要禁用中断.


顺便说一句:我自己已经编写了几个引导加载程序,并且通常在引导加载程序的整个运行时中禁用中断.在保护模式下,我最终重新启用它们.Linux 4.2处理它类似.如果您有兴趣,请阅读其源代码(/arch/x86/boot/)或来自Minix的源代码!

  • 实际上,在 x86 上,由于特殊规则,在第一种情况下不需要禁用中断:在 `pop %ss` 后一个周期内中断被禁用,因此您有时间设置堆栈指针。 (2认同)