上一篇文章学习了:OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门

本篇文章接着上一篇文章学习中断任务。

我们在前面文章中一直在说通过中断发起任务切换,本文就是将之前没有说明白的内容:通过中断发起任务切换讲明白。

1、 中断任务

当中断和异常发生时,如果根据中断向量从IDT中找到的描述符是任务门,则不是进行一般的中断处理过程,而是发起任务切换。如下图,是通过中断发起任务切换的原理:

用中断发起任务切换,直觉上的好处是方便。比如,因为硬件中断的发起是客观的,很容易用它来实现一个剥夺式的、抢占式的多任务系统。这就是硬件调度机制。

不过,这并不是它最主要的目的。想象一下,当前任务正在执行的时候,突然发生了终止类型的异常,比如双重故障,会怎么样?在这种情况下,想要用iretd指令返回到哪个任务继续执行时不可能的了。

在这种情况下,如果把双重故障的处理程序定义成任务,非常恰当。当双重故障发生时,执行任务切换,切换到内核中的任务中去,从容的将发生故障的任务从从系统中抹去,回收内存空间,然后重新调度其他任务执行,会是最好的解决办法。

具体的说,在中断机制中使用任务门有以下好处:

  • 被中断的那个程序或者任务的整个执行环境可以被完整的保存起来(保存带它的TSS中)
  • 由于接管任务的是一个全新的任务,因此,可以使用一个全新的0特权级栈。这可以有效的防止因当前任务的0特权级栈遭到破坏而使整个系统崩溃
  • 由于是切换到一个新的任务,因此,它有一个独立的地址空间

当然,和一般的中断胡成立过程相比,利用中断发起任务切换也有不利的一面:那就是速度很慢,毕竟要保存大量的机器状态,并进行一些列的特权级和内存访问的检查。

由中断和异常而发起的任务切换时,不再保存CS、EIP的状态,但是在任务切换工作完成后,处理器要把错误代码压入新任务的栈中(如果有错误代码的话)。

任务是不可重入的,因此,在进入中断任务之后和执行iretd指令之前,必须关中断,以防止因相同的中断再次发生而产生常规保护异常。

2、错误代码

上面提到了错误代码。下面我们简单介绍错误代码。

有些异常产生时,处理器会在异常处理程序或者中断任务的栈中压入一个错误代码。通常,这意味着异常和特定的段选择子或者中断向量有关。

如下图是一个错误代码的格式:

  • EXT位:异常是由外部事件引起的。此位为1时,表示异常是由NMI、硬件中断等引发的。
  • IDT位:用于指示描述符的位置。次位为1时,表示段选择子的索引部分(错误代码的位15-位3)是指向中断描述符表(IDT)的。为0时,表示段选择子的索引部分是指向GDT或者LDT的。
  • TI位 :仅在IDT位为0的时候才有意义。当TI=0时,表示段选择子的索引部分指向GDT,否则指向LDT。
  • 段选择子的索引部分用于指示GDT/LDT内的段描述符,或者IDT内的门描述符,它就是我们平时所用的段选择子段选择子的高13位
  • 有时候,错误代码可能全是0,这表示异常的产生并非由于引用了一个特定的段,也有可能是想要引用一个段,但是那个段的描述符是空的。

3、总结

本文主要学习通过中断发起的任务切换,以及学习以下错误代码的格式以及各个位代表的含义。

详细的内容还是要参考原书籍,这里只是做一个简单的总结。

学习探讨加个人:
qq:1126137994
微信:liu1126137994