屏蔽与使能中断

根据操作系统原理的知识,我们知道如果没有在硬件级保证读内存-修改值-写回内存的原子性,我们只能通过复杂的软件来实现同步互斥操作。但由于有开关中断和test_and_set_bit等原子操作机器指令的存在,使得我们在实现同步互斥原语上可以大大简化。

在ucore中提供的底层机制包括中断屏蔽/使能控制等。kern/sync.c中实现的开关中断的控制函数local_intr_save(x)和local_intr_restore(x),它们是基于kern/driver文件下的intr_enable()、intr_disable()函数实现的。具体调用关系为:

  1. 关中断:local_intr_save --> __intr_save --> intr_disable --> cli
  2. 开中断:local_intr_restore--> __intr_restore --> intr_enable --> sti

最终的cli和sti是x86的机器指令,最终实现了关(屏蔽)中断和开(使能)中断,即设置了eflags寄存器中与中断相关的位。通过关闭中断,可以防止对当前执行的控制流被其他中断事件处理所打断。既然不能中断,那也就意味着在内核运行的当前进程无法被打断或被重新调度,即实现了对临界区的互斥操作。所以在单处理器情况下,可以通过开关中断实现对临界区的互斥保护,需要互斥的临界区代码的一般写法为:

  1. local_intr_save(intr_flag);
  2. {
  3. 临界区代码
  4. }
  5. local_intr_restore(intr_flag);
  6. ……

由于目前ucore只实现了对单处理器的支持,所以通过这种方式,就可简单地支撑互斥操作了。在多处理器情况下,这种方法是无法实现互斥的,因为屏蔽了一个CPU的中断,只能阻止本地CPU上的进程不会被中断或调度,并不意味着其他CPU上执行的进程不能执行临界区的代码。所以,开关中断只对单处理器下的互斥操作起作用。在本实验中,开关中断机制是实现信号量等高层同步互斥原语的底层支撑基础之一。