`
izuoyan
  • 浏览: 8880281 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【操作系统原理】保护模式下Intel 80x86 CPU 硬件中断过程

 
阅读更多

保护模式下Intel 80x86 CPU 硬件中断过程

大学学操作系统原理的时候,感觉进程和文件似乎是介绍最多的两块内容,但慢慢发现,要想理解清楚操作系统的工作机制,如果按知识学习的先后顺序排,中断应当是比较靠前的才对,只有理解了中断的机制,才有可能真正理解进程,文件系统,设备等等其他的概念。

中断实际上为OS里很多概念的具体实现提供了一个基本的保证,比如进程的调度、设备的访问、用户态和内核态的切换,各种异常的处理等等都需要中断的参与,甚至连对临界资源的安全访问也需要中断的支持,这足以说明中断是可以作为一个了解操作系统工作原理和具体机制的入口点的,而不仅仅只是作为相关书籍里独立的一个章节来理解。

由于中断的机制和实现是和硬件密切相关的,这里只总结一下Intel 80x86系列CPU的中断在硬件层面上处理过程。

1. 中断和异常的概念区别

Intel的官方文档[1]里将中断和异常理解为两种中断当前程序执行的不同机制。这是中断和异常的共同点。不同点在于:

中断(interrupt)是异步的事件,典型的比如由I/O设备触发;

异常(exception)是同步的事件,典型的比如处理器执行某条指令时发现出错了等等。

中断又可以分为可屏蔽中断和非可屏蔽中断,异常又分为故障、陷阱和异常中止3种,它们的具体区别很多书籍和官方文档都解释的比较清楚这里不再赘述。

关于它们的区别有两点是需要注意的:

1)平常所说的屏蔽中断是不包括异常的,即异常不会因为CPUIF位被清(关中断,指令:cli)而受影响,比如缺页异常,即使关了中断也会触发CPU的处理。

2)通常说的int 80h这种系统调用使用的中断方式实际上硬件上是理解为异常处理的,因此也不会被屏蔽掉,这也很好理解,int 80h这种中断方式是程序里主动触发的,对于CPU来说属于同步事件,因此也就属于异常的范畴。

2. 中断(异常)处理过程

需要明确的一点是CPU对于中断和异常的具体处理机制本质上是完全一致的,即:

CPU收到中断或者异常的信号时,它会暂停执行当前的程序或任务,通过一定的机制跳转到负责处理这个信号的相关处理程序中,在完成对这个信号的处理后再跳回到刚才被打断的程序或任务中。这里只描述保护模式下的处理过程,搞清楚了保护模式下的处理过程(更复杂),实模式下的处理机制也就容易理解了。

具体的处理过程如下:

0)中断响应的事前准备:

系统要想能够应对各种不同的中断信号,总的来看就是需要知道每种信号应该由哪个中断服务程序负责以及这些中断服务程序具体是如何工作的。系统只有事前对这两件事都知道得很清楚,才能正确地响应各种中断信号和异常。

[a] 系统将所有的中断信号统一进行了编号(一共256个:0255),这个号称为中断向量,具体哪个中断向量表示哪种中断有的是规定好的,也有的是在给定范围内自行设定的。

中断向量和中断服务程序的对应关系主要是由IDT(中断向量表)负责。操作系统在IDT中设置好各种中断向量对应的中断描述符(一共有三类中断门描述符:任务门、中断门和陷阱门),留待CPU查询使用。而IDT本身的位置是由idtr保存的,当然这个地址也是由OS填充的。

下面的示意图显示了IDT的基本结构和IDTR是如何指示IDT的位置和长度的:

[b] 中断服务程序具体负责处理中断(异常)的代码是由软件,也就是操作系统实现的,这部分代码属于操作系统内核代码。也就是说从CPU检测中断信号到加载中断服务程序以及从中断服务程序中恢复执行被暂停的程序,这个流程基本上是硬件确定下来的,而具体的中断向量和服务程序的对应关系设置和中断服务程序的内容是由操作系统确定的。

1CPU检查是否有中断/异常信号

CPU在执行完当前程序的每一条指令后,都会去确认在执行刚才的指令过程中中断控制器(如:8259A)是否发送中断请求过来,如果有那么CPU就会在相应的时钟脉冲到来时从总线上读取中断请求对应的中断向量[2]

对于异常和系统调用那样的软中断,因为中断向量是直接给出的,所以和通过IRQ(中断请求)线发送的硬件中断请求不同,不会再专门去取其对应的中断向量。

2)根据中断向量到IDT表中取得处理这个向量的中断程序的段选择符

CPU根据得到的中断向量到IDT表里找到该向量对应的中断描述符,中断描述符里保存着中断服务程序的段选择符。

3)根据取得的段选择符到GDT中找相应的段描述符

CPU使用IDT查到的中断服务程序的段选择符从GDT中取得相应的段描述符,段描述符里保存了中断服务程序的段基址和属性信息,此时CPU就得到了中断服务程序的起始地址。

这里,CPU会根据当前cs寄存器里的CPLGDT的段描述符的DPL,以确保中断服务程序是高于当前程序的,如果这次中断是编程异常(如:int 80h系统调用),那么还要检查CPLIDT表中中断描述符的DPL,以保证当前程序有权限使用中断服务程序,这可以避免用户应用程序访问特殊的陷阱门和中断门[3]

如下图显示了从中断向量到GDT中相应中断服务程序起始位置的定位方式:

4CPU根据特权级的判断设定即将运行的中断服务程序要使用的栈的地址

CPU会根据CPL和中断服务程序段描述符的DPL信息确认是否发生了特权级的转换,比如当前程序正运行在用户态,而中断程序是运行在内核态的,则意味着发生了特权级的转换,这时CPU会从当前程序的TSS信息(该信息在内存中的首地址存在TR寄存器中)里取得该程序的内核栈地址,即包括ssesp的值,并立即将系统当前使用的栈切换成新的栈。这个栈就是即将运行的中断服务程序要使用的栈。紧接着就将当前程序使用的ss,esp压到新栈中保存起来。

6)保护当前程序的现场

CPU开始利用栈保护被暂停执行的程序的现场:依次压入当前程序使用的eflagscseiperrorCode(如果是有错误码的异常)信息。

官方文档[1]给出的栈变化的示意图如下:

7)跳转到中断服务程序的第一条指令开始执行

CPU利用中断服务程序的段描述符将其第一条指令的地址加载到cseip寄存器中,开始执行中断服务程序。这意味着先前的程序被暂停执行,中断服务程序正式开始工作。

8)中断服务程序处理完毕,恢复执行先前中断的程序

在每个中断服务程序的最后,必须有中断完成返回先前程序的指令,这就是iret(或iretd)。程序执行这条返回指令时,会从栈里弹出先前保存的被暂停程序的现场信息,即eflags,cs,eip重新开始执行。如果存在特权级转换还会弹出ssesp,这样也意味着栈也被切换回原先使用的栈了。

这里有个地方需要注意:如果此次处理的是带有错误码(errorCode)的异常,CPU在恢复先前程序的现场时,并不会弹出errorCode,也就是说CPU似乎忘记了曾经压过一个errorCode入栈,因此要求相关的中断服务程序在调用iret返回之前需要主动弹出errorCode

参考书目:

[1] Intel 64 and IA-32 Architectures Software Developers Manual Volume 1 Basic Architecture

[2] 《微型计算机接口技术及应用》,华中科技大学出版社,刘乐善 主编

[3] 《深入理解Linux内核》,第三版,中国电力出版社

分享到:
评论

相关推荐

    操作系统开发相关软件和资料(2/3)

    操作系统开发相关软件和资料:Bochs-2.4.5虚拟机,NASM软件和中文文档,Linux0.0.1、Linux0.11源代码,保护模式编程详解,80x86指令资料,微机原理及接口技术文档

    西安理工大学 微机原理课件

    本章全面系统地介绍了80x86指令系统的寻址方式、指令格式和各类指令的功能及应用。该指令系统的特点是:指令格式灵活,采用可变长度指令格式,指令长度可在1~6个字节之间变化;寻址能力强,对操作数的寻址有7种不同...

    操作系统开发相关软件和资料(1/3)

    操作系统开发相关软件和资料:Bochs-2.4.5虚拟机,NASM软件和中文文档,Linux0.0.1、Linux0.11源代码,保护模式编程详解,80x86指令资料,微机原理及接口技术文档

    操作系统开发相关软件和资料(3/3)

    操作系统开发相关软件和资料:Bochs-2.4.5虚拟机,NASM软件和中文文档,Linux0.0.1、Linux0.11源代码,保护模式编程详解,80x86指令资料,微机原理及接口技术文档

    清华大学 汇编语言程序设计 课件

    (2)80x86计算机组织与保护模式、X86指令系统与寻址方式、C与X86汇编、X86汇编编程; (3)MIPS汇编。 课程强调汇编语言的软硬件分界与桥梁作用,使得学习者能把程序的执行与计算机的工作过程紧密联系起来,以便...

    深入分析Linux_内核源代码-pdf版

    然后概要介绍了PC机的硬件组成结构、编制内核使用的汇编语言和C语言扩展部分,并且重点说明了80x86处理器在保护模式下运行的编程方法。接着详细介绍了Linux内核源代码目录树组织结构,并依据该组织结构对所有内核...

    微机原理及接口技术

    5.3.2 8086 CPU 最大模式下 的系统配置 ............................ 132 5.4 80386 CPU 的引脚功能..................... 135 5.5 80486 CPU 的引脚功能..................... 138 5.6 Pentium 微处理器的 引脚...

    linux-0.11:这个repo用来分析linux 0.11源码及整个现代多任务操作系统实现原理

    80x86的保护模式及其编程 EFLAGS 内存管理寄存器,GDTR,LDTR,IDTR和TR,用于指定内存分段管理所用系统表的基地址GDTR [32位线性基地址,16位表长度] IDTR [32位线性基地址,16位表长度] LDTR [16位段选择符,32位...

Global site tag (gtag.js) - Google Analytics