tags:
- 操作系统
categories: - 操作系统
link: https://www.notion.so/OS-018-Part-3-e522271c509c4004aa599907a7e072cf
notionID: e522271c-509c-4004-aa59-9907a7e072cf
title: OS-018-李煦-Part 3
[[操作系统]]
3.1. 中断和异常处理概述
中断是指在程序执行过程中,由硬件或软件发出的一个信号,用于打断CPU当前正在执行的指令流,转而去执行相关的中断处理程序。中断可以用来处理外部设备的请求、系统调用、时钟定时等事件。
异常是指在程序执行过程中发生的一些非正常的情况,例如除零错误、访问越界、非法指令等。异常的发生会导致处理器中断正在执行的指令流,并跳转到相应的异常处理程序中。
处理器在接收到中断或异常信号后,会暂停当前的指令流执行,并将当前的执行现场(包括寄存器状态等)保存起来。然后,根据中断或异常的类型,在中断向量表或异常向量表中找到相应的处理程序入口地址,并跳转到对应的处理程序中执行。处理程序执行完毕后,处理器会恢复之前保存的执行现场,并继续执行被打断的指令流。
实模式和保护模式下的中断向量表是不一样的。实模式下,中断向量表是一个固定的存储在内存的位置,由256个16字节的中断描述符组成。而在保护模式下,中断向量表是存储在内存中的一个数据结构,被称为中断描述符表(IDT
),其中的每个中断门(Interrupt Gate)都包含了中断处理程序的入口地址和访问权限等信息。
3.2. 有关中断和异常了解性的内容
中断和异常向量:中断和异常向量是中断和异常处理程序的入口点。处理器根据中断或异常的类型选择相应的向量。
中断源和异常源:中断源是指可以引发中断的外部设备或事件,例如时钟中断或硬件设备的中断。异常源是指在执行指令时可能发生的错误或异常情况,例如除零错误或非法指令。
异常的分类:异常分为三种类型:故障(fault)、陷阱(trap)和中止(abort)。故障是可修复的错误,表示出现了某种异常情况,但可以通过一些操作或修复措施来继续执行。陷阱是一种用于调试或记录信息的异常,它可以由调试工具或操作系统使用。中止是不可恢复的错误,表示出现了严重的错误或非法操作,导致程序的终止。
程序或任务的重新执行:当处理器发生中断或异常时,它会暂停当前的程序或任务,转而执行相应的中断或异常处理程序。处理程序执行完毕后,处理器可以选择继续执行中断或异常发生前的程序,也可以选择终止当前程序或任务,并执行其他操作。
开启和禁止中断:处理中断和异常向量器提供了一些特殊的指令,用于开启和禁止中断。通过设置处理器的标志中断源和异常源寄存器中的中断标志位,可以控制中断的开启和禁止。当中断被禁止时,处理器不会响应外部设备的中断请求程序或任务的重新执行。
异常和中断的优先级:不同的异常和中断可能具有不同的优先级。处理开启和禁止中断器使用优先级来确定处理哪个异常或中断。通常,紧急的和重要的异常或中断具有较高的优先级,而较低重要性的异常或中断具有较低的优先级。处理器根据优先级和处理程序的可用性来选择要处理的异常或中断。
3.3. 中断描述符表
如何构成?
中断描述符表(IDT)的结构如下所示:
IDT存储一组门描述符,这些门描述符提供对中断和异常处理程序的访问。像GDT一样,IDT不是一个片段。IDT基址的线性地址包含在IDT寄存器(IDTR
)中。IDT中的门描述符可以是中断、陷阱或任务门描述符。
如何获得中断处理程序的地址?
中断描述表为每一个异常或者中断向量对应的例程或者任务分配了门描述符。异常或者中断向量号乘以8就能得到IDT中的描述符的索引(也就是门描述符包含的字节的数量)。
为了访问中断或异常处理程序,处理器首先从内部硬件、外部中断控制器或通过INT、INTO、INT 3或BOUND指令从软件接收一个中断向量(中断号)。中断向量提供IDT的索引。如果选择的门描述符是中断门或陷阱门,则以类似于通过调用门调用过程的方式访问相关的处理程序过程。如果描述符是任务门,则通过任务开关访问处理程序。
如何设置中断描述符表寄存器?
LIDT和SIDT指令分别用来装载和保存IDTR
寄存器的值。LIDT指令使用包含基址和限长的内存操作数装在IDTR
寄存器,这个指令只有当CPL为0的时候才能使用。SIDT指令将IDTR
寄存器中的基址和限长保存到内存操作数中。可以在任何的特权级别下使用。
3.4. IDT 描述符
任务门
IDT中使用的任务们的格式和GDT或者LDT中使用的任务门的完全一致。任务门里面包含异常或者中断处理任务的TSS的段选择符号
中断门
中断门和调用门非常相似。包含一个远指针(段选择符号和位移),处理器用它们来执行流转移动到异常或者中断处理代码中的处理程序。
陷阱门
陷阱门也同样和调用门相似。所以也有中断门具有的性质。
3.5. 中断与异常处理
中断过程调用的流程是怎样的
当处理器转去执行一个异常或者中断处理程序的时候,会将EFLAGS寄存器,CS寄存器,EIP寄存器的当前值保存进栈。
CS 和 EIP 寄存器为中断提供了一个返回地址指针
如果异常同时产生了一个出错码,那这个值也会压到栈里面,在EIP之后。
如何判断中断处理过程与被中断任务的优先级?
提供优先级判断的是门描述符,这些门提供了一种访问运行在不同于应用程序特权级别的系统过程和处理程序的方法。例如一个对调用门的调用可以访问和当前代码段特权相同或者数字更低(特权更高)的代码段中的过程。执行访问特权检查的处理器比较调用们的特权和调用门指向的目的代码的CPL(Current Privilege Level)。如果允许访问,处理器从调用门得到目标代码段的选择符号
和偏移地址
。
不同优先级上,处理方式一样吗?
不同优先级上处理的方式是不一样的,如果没有发生特权级的改变,被中断的进程和处理进程使用的是同一个堆栈,也就是被中断进程的堆栈;但是当特权级别发生改变的时候,被中断的进程和处理例程将使用是不同堆栈,而此时堆栈的指针由TSS中的相应字段给出。也就是说处理历程使用的是被中断进程的高特权级别堆栈,每个任务都有自己的独立的高特权级别堆栈。
如果发生堆栈切换,处理器会做哪些操作?
只有当处理的历程将运行于更高一级的特权级别上的时候会发生堆栈的切换。这个时候指向返回后使用的栈指针也会被压入栈中。(SS
和ESP
用作处理例程返回之后的栈指针)而处理例程要使用的堆栈段选择符号和栈指针则从当前进程的TSS中得到,处理器将EFLAGS
,SS
,ESP
,CS
,EIP
,还有出错码从当i前进程的堆栈拷贝到处理例程的堆栈。
如果没发生堆栈切换,处理器会做哪些操作?
当处理器转去执行一个异常或者中断处理例程的时候,会将EFLAGS寄存器,CS寄存器,EIP寄存器的当前值保存进栈如果异常的时候产生了一个出错码,那么这个值也会压到栈里面,位于EIP之后。如果没有发生堆栈切换,说明处理历程和被中断的进程就处于同一个特权级别,那么处理历程**使用当前堆栈*
中断处理过程后,如何返回,处理器做了哪些操作?
从终端或者中断处理例程中返回必须使用IRET
指令,IRET
指令和RET
指令的唯一不同就在于前者将恢复标志位。只有当CPL为0的时候,EFLAGS
寄存器的IOPL
位才恢复。IF位只有在CPL小于或者等于 IOPL 的时才改变。如果在调用例程的时候堆栈发生了切换,那么在返回的时候,IRET指令还将切换回被中断进程的堆栈。
异常和中断处理过程的保护
异常和中断处理例程的特权级别的保护,同通过调用门的普通进程调用的特权级别保护相似。如果异常和中断处理例程的特权级别比CPL低,那么处理器就不允许这样的调用发生,否则就将产生通用的保护异常( # GP) ,异常和中断处理例程的保护机制在以下几个方面有差异:
RPL : 请求访问特权
当发生中断或者产生异常的时候,不会检查RPL。
只有当中断或者异常是由INT n
,INT 3
或者INTO
产生的时候,处理器才会检查中断和陷阱门的DPL;这个时候CPL
一定要小于或者等于门的DPL;目的:防止了运行在3级的应用程序或者进程使用软件中断来访问异常处理的关键代码。 而对于硬件产生的中断或者处理器检测到的异常,就会不忽略掉DPL。
可以将异常或者中断处理例程放到一致的代码段中。但是这样的技术只适用于访问堆栈上数据的处理例程。 如果这个例程需要访问数据段中的数据,那么这个数据段必须能够被处在3级特权级别的程序访问,就会导致数据无法保护。
异常和中断处理过程的标志使用方式
通过中断门或者陷阱门访问异常或者中断处理例程的时候,在将EFLAGS
寄存器的内容保存入栈之后,处理器会清除EFLAGS
的TF位。这样做的原因是可以禁止指令跟踪,以使得中断响应不受影响。后继的IRET指令就是用保存在栈中的EFLAGS
寄存器中的值,恢复TF位。
中断门与陷阱门的唯一区别是什么?
终端们和陷阱门的处理器处理EFLAGS的IF位的方式不同。通过中断门访问异常或者中断处理例程的时候,处理器清除IF位,为的是阻止另外的中断干扰当前的中断处理例程。陷阱门调用处理例程的时候IF位不受到影响。