您好、欢迎来到现金彩票网!
当前位置:双彩网 > 向量屏蔽 >

《一个操作系统的实现》(三):4中断和异常5保护模式下的IO

发布时间:2019-06-16 19:50 来源:未知 编辑:admin

  前面讲到了实模式下用int 15h得到内存信息,然后在保护模式下把它们显示出来。保护模式下中断机制发生了很大的变化,原来的中断向量表被IDT(Interrupt Descriptor Table,中断描述符表)代替,实模式下能用的BIOS中断在保护模式下已经不能用了。IDT可以将每一个中断向量和一个描述符对应起来。IDT中的描述符可以是中断门描述符、陷阱门描述符、任务门描述符。尽管IDT在形式上与实模式下的向量表非常不同,但它也是一种向量表。

  中断门和陷阱门的作用机理几乎一样,只不过使用调用门时用call指令,而在这里我们使用int指令。

  每一种中断(异常)都会对应一个中断向量号,而这个向量号通过IDT就与相应的中断处理程序对应起来。保护模式的中断和异常见下表:

  Fault(错误)可被更正的异常,更正后程序可继续执行。当一个fault发生时,处理器会把产生fault的指令之前的状态保存起来。异常处理程序的返回地址将会是产生fault的指令,而不是其后的那条指令。

  Trap(陷阱)一种在发生trap的指令执行后立即被报告的异常,它也允许程序或任务不失连续性地继续执行。异常处理程序的返回地址将会是产生trap的指令之后的那条指令。

  About(终止)不总是报告精确异常发生位置,它不允许程序或任务继续执行,而是用来报告严重错误。

  外部中断(即由硬件产生的)需要建立硬件中断与向量号之间的对应关系。分为可屏蔽中断和不可屏蔽中断两种。不可屏蔽中断由CPU的NMI引脚接收,可屏蔽中断则由CPU的INTR引脚接收。可屏蔽中断与CPU的关系是通过对可编程中断控制器8259A(可以认为是中断机制中所有外围设备的一个代理,这个代理不但可以根据优先级在同时发生中断的设备中选择应该处理的请求,而且可以通过对其寄存器的设置来屏蔽或打开相应的中断)建立起来的。

  内部中断(由int n产生)类似于调用门的使用,n即为向量号。

  有两片级联的8259A与CPU相连,每个8259A有8根中断信号线A进行设置,可以使这些外设发出的中断请求与中断向量对应起来。在BIOS初始化它的时候,IRQ0~IRQ7被设置为对应向量号08h~0Fh,但保护模式下这些向量号已被占用,所以需要重新设置。8259A是可编程中断控制器,对它的设置可通过向相应端口写入特定的ICW(Initialization Command Word)来实现。主8259A对应的端口地址是20h和21h,从8259A对应的端口地址是A0h和A1h。初始化过程(不能颠倒顺序):往端口20h或A0h写入ICW1-往端口21h或A1h写入ICW2-往端口21h或A1h写入ICW3-往端口21h或A1h写入ICW4(注:2、3、4的写入的端口相同)。

  还有一个东西叫做OCW(Operation Control Word),共有OCW1、OCW2、OCW3共三个,用于屏蔽或打开外部中断(向21h或A1h写入OCW1即可,实际上OCW1被写入了中断屏蔽寄存器IMR中,当一个中断到达,IMR会判断此中断是否应被丢弃)或发送EOI给8259A以通知它中断处理结束。

  对于EOA,每一次中断处理结束,需要发送一个EOI给8259A,以便继续接受中断。发送EOI通过向20h或A0h端口写OCW2实现。

  可屏蔽中断与NMI的区别在于是否受到IF位的影响,而8259A的中断屏蔽寄存器(IMR)也影响着中断是否会被响应。所以外部可屏蔽中断受IF位(需为1)和IMR位(需为0)的影响。

  实际应用中,中断的产生大多带有特权级变换,规则与用call指令调用一个调用门的规则完全一样。如果中断或异常发生时没有特权级变换,则eflags、cs、eip、将依次被压入堆栈,如果有出错码,则出错码最后被压栈。如果有特权级变换,ss和esp被压入内层堆栈,然后是eflags、cs、eip、出错码(若有的话)。总之不管怎样,中断或异常发生时,堆栈都会发生变化。

  从中断或异常返回时必须使用指令iretd,与ret的区别就在于它同时改变eflags的值。需要注意的是,只有当CPL为0时,eflags中的IOPL域才会改变,而且只有当CPL小于等于IOPL时,IF才会改变。还要注意的是,iretd执行的时候Error Code不会被自动从堆栈中弹出,所以执行它之前要先将它从栈中清除掉。

  还有一点,中断门和陷阱门有一个小区别。由中断门向量引起的中断会复位IF,因为可以避免其他中断干扰当前中断的处理,随后的iret指令会从堆栈上回复IF的原值;而通过陷阱门产生的中断不会改变IF。

  I/O敏感指令:in、ins、out、outs、cli、sti,它们只有在CPL小于等于IOPL时才能执行,如果低特权级的指令试图访问这些I/O敏感指令将会导致常规保护错误(#GP)。

  可以改变IOPL的指令只有popf和iretd,但只有运行在ring0的程序才能将其改变,低特权级的无法改变,但也不会产生异常(会维持原样)。指令popf也可用来改变IF(就像执行了cli和sti)。但在这种情况下,popf也变成了I/O敏感指令,只有CPL小于等于IOPL时,popf才能改变IF,否则保持原样(不会产生异常)。

  I/O位图基址是一个以TSS的地址为基址的偏移,指向的便是I/O许可位图。它的每一位表示一个字节的端口地址是否可用(0为可用,1为不可用)。由于每个任务都可以有单独的TSS,所以每个任务可以有它单独的I/O许可位图。I/O许可位图必须以0FFh结尾。如果I/O位图基址大于或等于TSS段界限,则表示没有I/O许可位图,如果CPL小于等于IOPL,则所有I/O指令都会引起异常。I/O许可位图的使用使得即便在同一特权级下不同的任务也可以有不同的I/O访问权限。

http://bluecaleel.com/xiangliangpingbi/148.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有