10 Day : 中断

前言:

目前我们的内核还是一个简单的while循环,大家可能会有疑问,while循环怎么执行其他功能呢,这里就要介绍一个很重要的点,那就是中断。,可以很负责的说操作系统就是由中断驱动的,CPU的并发也是由中断实现。

本日参考资料:

《操作系统真象还原》


一,什么是中断?

🌟操作系统是由中断驱动的,CPU的并发也是由中断实现的🌟

为了更好理解这句话我来举一个例子。

今天你的爸爸妈妈都不在家,身为学生的你主要任务就是看书,但是爸爸妈妈交代给你的任务有煮饭晒衣服等快递

这个时候的你有三种选择:

1,我啥也不管,我就看书

2,我看书,每隔一段时间我就去看饭煮好没,衣服洗完没,快递员到门口没

3,我还是照常看书,但是我根据每一个事情的声音来判断事情是否完成好了,当煮饭好了的时候就电饭煲发出“饭好了”,衣服洗好了洗衣机就发出”衣服洗好了”,快递到了后快递员会按门铃。


第一种方法,那肯定是要挨爸爸妈妈打的,因为你什么事情都没完成

第二种方法,固然是可以的,但是你看书的效率就会很低,因为你每次要离开书桌去检查

第三种方法,这种方法是最好的,你只需要通过声音得知任务是否完成,此时在打断当前读书的任务,去晒衣服,拿快递等等,而这就是我们所说的中断


这个时候我们把 学生比作CPU看书比作读指令煮饭晒衣服比作其他要处理的程序声音比作中断,在计算机中CPU是没有意识的,他不知道该什么时候运行谁的指令,所以他只会傻傻的埋头做手上的事情,但是当他接受到中断时会根据中断的类型来决定接下来要做的事情,从而实现并发,大家想想我们之前的内核是一个while(1),如果想跳出这个while执行程序那就需要通过中断来去执行其他用户程序。


二,详细聊聊中断


1,中断分类

中断可以通过硬件和软件来分为外部中断内部中断,首先我们先来聊聊外部中断。

① 外部中断

外部中断:即中断源是某个硬件,所以外部中断又称为硬件中断。


CPU接收中断信号需要引脚 ,但是硬件是非常多的而且基本上是无上限的,所以不能每个硬件分配一个引脚,于是根据硬件信号类型使用了两个公共引脚 INTR NMI

 根据这两个引脚又将外部中断分为两个类型:可屏蔽中断不可屏蔽中断


可屏蔽中断

顾名思义就是可以被屏蔽可以不管的中断,可以通过eflags的IF位将这些外设的中断全部屏蔽。

中断的时候会执行中断程序,中断程序不是立即执行的,他会被分为上下两部分

  • 上半部分:被认为是紧急部分,也就是中断应答和硬件复位,此时不能受其他中断影响需要关闭中断,执行完后开启
  • 下半部分:程序部分,并不是很紧急,可以被其他中断打断,具体执行时间等待进程调度来执行

打个比方:网卡,网卡有个缓冲区用来存储数据,缓冲区很小,如果超出缓冲区就会抛弃后面到来的数据,所以他的上半部分就需要CPU迅速把缓冲区的数据给拿到内核缓冲区,下半部分关于数据的处理就没那么急可以之后处理。


不可屏蔽中断

不可屏蔽中断意味着,计算机寄了,他的运行之旅到此结束了,一般内存出错,掉电,总线校验出错就会发出这个中断,就算屏蔽也没用,你的计算机已经要宕机了还有什么用呢,由于这个中断属于硬件方面的,要交给硬件工程师来维修,所以这些错误给他分配的中断号只有一个 中断向量号2

② 内部中断

内部异常一般是由软件内部发起的,它分为两类:软中断异常


软中断

软中断就是由软件主动发起的中断,他不一定是内部的某种错误

  • int 8立即数:我们之后最常用的指令,它代表了256种中断类型
  • int3:中断向量号3,机器码为0xcc,目的是用作调试(例如:bochs的调试),原理是父进程fork出一个子进程,并将断点的地址的机器码的第一个字节备份并替换为0xcc,当指令执行到断点时,触发中断,并且将当前的寄存器内容保存到栈中,用户便可以通过栈查看相关信息,之后再通过iret指令退出中断
  • into:中断向量号4,触发它需要看eflags中的of位是否为1,为1才触发中断。
  • bound:中断向量号5,数组越界
  • ud2:中断向量号6,未定义指令,即CPU无法识别的指令

其实除 int 8立即数以外其他的也可以称为异常。


异常

异常即CPU运行期间产生的错误,他不受eflags中的if标志位所影响,其根据严重情况分为三种等级:

  • Fault:这个是最轻的等级,即当CPU运行时,发现此类异常时,CPU将机器状态恢复到异常之前的状态,之后调试中断处理程序去解决异常,然后退出中断处理程序时返回的地址指向异常的那条指令,并进行重试。最经典的就是缺页异常 page fault。
  • Trap:类似于int3指令,使当前的软件停下来,通常出现在调试过程中,一般返回异常的下一条指令地址
  • Abort:最严重的情况,一般是软件无法执行下去了,无法修复直接从进程表中将该程序移除。

Error Code


三,中断描述符表


① 中断描述符表

存储中断处理程序入口的表

保护模式:中断描述符表 IDT

实模式:中断向量表 IVT

存储:中断描述符,陷阱门描述符,任务门描述符

段描述符描述一片内存区域

门描述符描述一段代码


 ② 各种门的介绍

  • 任务门 

位置:任务门存在于GDT,LDT,IDT中

作用:是用于提供任务切换机制,任务门配合TSS一起使用,但是现在的操作系统大多数都不用他,我就不多说他了 

type值:0101

  • 中断门 

位置: 只存在IDT中

作用:包含中断处理程序所在的段的段选择子段内偏移地址,进入中断后会将标志寄存器的IF位置为0,自动关闭中断,避免中断嵌套

type值:1110

  • 陷阱门 

位置:只存在IDT中

作用:和中断门相似,只是不会将eflags的IF位置为0

type值:1111

  • 调用门 

位置:GDT和LDT中

作用:提供给用户进程进入0特权级的方式,DPL为3,只能用call和jmp调用

type值:1100


③ IDTR 

中断描述符 (8字节), IDTR(48位), 描述符个数 64KB/8 = 8129

用法:lidt 48位内存数据


 ④ 处理过程

中断处理的过程分为CPU内和CPU外,CPU外是由8259A芯片所代理控制,之后会讲,我们着重讲CPU内的操作。

  • 1,处理器根据中断向量号定位中断描述符

处理器收到一个中断向量号时,会将其*8,然后将结果带入到IDT中去寻找对应的中断描述符

  • 2,处理器进行特权级检查

中断向量号只是个整数,所以不涉及到RPL,但是他的特权级要介于门描述符和目标代码段DPL之间。

(在这里可以把门描述符当作资源,门描述符选择子的代码段当作代码)


(a) 门描述符检查,如果是由软中断int n,int 3,into引发的中断,这代表该中断有用户发起,那么用户的特权级应该大于门描述符特权级(资源非一致性)

(b) 门描述符选择子检查,检查当前的CPL和选择子代码段的DPL,要求CPL的特权级必须低于代码段的DPL,因为中断调用的特权级变化是有低到高变化的(代码一致性)

外设中断和异常无需进行(a)步骤

  • 3, 执行中断处理程序

特权级通过后,直接把目标代码段加载到代码段寄存器


 ⑤ cli与sti

大伙都知道了,eflags的IF位关闭开启,对于中断有着很重要的作用,处理器专门提供了两个指令来关闭开启中断

cli则为关中断,IF设置位0,sti位开中断,IF设置位1  


⑥ NT与TF 

NT:用于任务嵌套,CPU将旧任务挂起,执行新任务,同时将NT位设为1,并且将上一个任务的TSS指针放入自己的TSS中,当CPU执行iret时,判断NT位是否为1,如果为1则代表嵌套调用。

TF:为0时表鼠禁止单步执行 


⑦ 中断发生时的压栈与出栈 

压栈

Ⅰ. 检查特权级,如果当前的CPL > DPL,即当前特权级低于代码段特权级,说明要发生特权级转移,此时要在对应特权级的TSS中找到相应的栈,将ESP,SS压入栈中由于SS是16位需要用高16位0填充位32位

Ⅱ. 将EFLAGS寄存器压入栈中

Ⅲ. 压入EIP和CS(和SS一样高16位0填充32位)

Ⅳ. 压入错误码,ERROR_CODE

如果没有发生特权级转移,就不会寻找新栈,也不会压入ESP和SS

                 

 栈顶往上的顺序是:ERROR_CODE,EIP,CS,EFLAGS,ESP,SS


出栈 

Ⅰ. 手动跳过错误码

Ⅱ. 弹出EIP和CS(高16位被抛弃),同时判断是否发送特权级变化,如果发生则进行Ⅳ(a)步骤反之Ⅳ(b)

Ⅲ. 弹出EFlags

Ⅳ(a). 此时特权级发生变化,则将ESP和SS弹出,还原栈

Ⅳ(b). 特权级未发生变化,则不继续弹出,因为使用的是旧栈,刚好恢复到的是调用前的状态。


⑧ 中断错误码 

错误码最主要的部分就是选择子

EXT:如果中断源是不可屏蔽事件则为1,否则为0

IDT:代表是否为中断向量表

TI :和段选择子一样,1代表GDT,0代表LDT


四,可编程中断控制器8295A

 这个时候请大家思考一个问题,当同时多个中断发送过来,CPU应该怎么办呢,把他存入队列还是舍弃呢,舍弃的话肯定不行,但是存入队列去选择这件事显然不是CPU皇上去做,这个时候就有一个中断仲裁负责处理这些事情,这个中断仲裁就是8295A


① 8295A的作用和架构

 8295A是控制和管理外部设备中断的中断仲裁设备,用于选出优先级最高的中断信号,存储中断信号

Intel处理器支持256个中断。一个8295A只有8个中断请求信号线,可以管理8个中断向量,这显然是不够的,所以为了支持更多的中断设备便有了级联架构,也就是占用一个中断向量的位置来连接另一个8295A,其可以管理的中断向量数为 7n+1。而根据级联的方式又分为了主片和从片,也就是主从模式。


② 8259A的内部结构和中断仲裁流程

 

INT:发送中断请求信号

INTA: 接收CPU的INTA接口的中断响应信号

IMR:屏蔽一些中断向量号

ISR:保存当前正在执行的中断向量号

PR:在IRR中寻找优先级最高的中断向量号,一般是向量号越低优先级越高(取决与OCW的设置,之后会说)

IRR:通过中断屏蔽寄存器的中断向量号暂存的地方,可以认为是中断向量号队列

流程:

  • 1,外设发出中断信号,通过主板的信号通路到达8259A的IRQ接口送入8259A,此时8259A检查IMR是否将该位屏蔽,如果屏蔽了则忽略该中断,反正放行
  • 2,放行过后的信号,会暂存在IRR中,将对应的IRR设为1
  • 3,PR立即根据当前的IRR,来挑选优先级最高的向量号
  • 4,此时INT向CPU的INTR接口发送中断请求信号
  • 5,CPU处理完当前指令后,立马向8259A芯片的INTA接口发送中断响应信号代表可以接受中断信号
  • 6,8295A收到这个消息后,立即将刚刚选出优先级最大的向量号在ISR中所对应的bit位置为1
  • 7,CPU再次向8259A的INTA接口发送信号,表明想获取向量号
  • 8,8259A用 起始中断向量号+IRQ接口号作为该设备的中断向量号,然后通过数据总线发送给CPU
  • 9,如果8259A的EOI通知为非自动模式,则当中断完成时,需要手动发送EOI信号,此时ISR中对应的BIT位才会置为0。如果时自动模式,当8295A接受到新的INTA,会自动将ISR当前执行BIT位置为0 (也就是说进入ISR后也有可能被其他优先级更高的向量号替换下来)

理解小贴士:

书上有一种比喻很有趣

CPU就是皇上,8259A就是大臣,中断信号则为奏折,每天早朝时,大臣都会将昨天收集到的奏折保存好,然后向皇上说一句:“老臣有本要奏”,皇上听到后回复一句:”8295A,有何事啊?",大臣听到后发现皇上心情不错有时间处理奏折,从多本奏折中挑出最重要的奏折,此时皇上说:“呈上来!”,于是8295A将奏折交给数据总线太监,皇上拿到太监那里的奏折后开始处理。


③ 8259A编程

8259A内部有两组寄存器,ICW初始化命令寄存器组(ICW1~4)OCW操作命令寄存器组(OCW1~3),设置8259A并不难,但是东西很多,所以请大家克服一下。


ICW

  • ICW1

作用:初始化连接方式中断信号的触发方式

写入端口:主片0x20端口,从片0xA0端口 


IC4:是否写入ICW4,x86系统必须为1

SNGL:1 为单片,0为级联

ADI:设置8085的调用时间间隔,x86无需设置

LTIM:中断检测方式,0为边沿触发,1为电平触发

第四位:代表他为ICW1

  • ICW2 

 作用:设置起始中断向量号

写入端口:主片0x21,从片0xA1


只填写T3~T7,每一个都是8的倍数,这个便是起始中断向量号

实际中断向量号 = 高五位+低三位

  • ICW3

 作用:设置主片和从片分别用哪个IRQ接口相连

写入端口:主片0x21,从片0xA1


主片模式: 置为1的那一位代表与从片相连,例如00000100,这代表2号接口与从片相连

从片模式:通过低三位确定主片连接的是否是自己(因为从片与主片相连的接口不是IRQ,所以从片无需记录自己的哪个接口与主片相连)

在做中断响应时,主片会发生中断信号和级联从片的IRQ接口号,这个时候,所有从片都会比对自己低三位是否一致。

  • ICW4

 作用:8259A的工作模式

写入端口:主片0x21,从片0xA1


SFNM:全嵌套模式,0位全嵌套,1为特殊全嵌套

BUF:8259A芯片是否工作在缓冲模式,0为非缓冲,1为缓冲

M/S:缓冲模式下,规定8259A为从片(0)还是主片(1),非缓冲模式无效

AEOI:自动结束中断,8259A要在收到中断结束信号后才能进行下一个中断处理,0为非自动需要手动结束,1为自动结束

µPM:表示处理器类型,0为8080和8085,1为x86


OCW

  • OCW1

 作用:屏蔽8259A上的外部设备的中断信号

 写入端口:主片0x21,从片0xA1


某位为1就代表该位置信号屏蔽,0则放行

  • OCW2(该操作器的操作数灵活多变注意!!)

作用:设置中断结束方式和优先级模式

 写入端口:主片0x20,从片0xA0


SL:指定优先等级,如果SL为1,可以使低三位来指定位于ISR寄存器中要终止的中断,如

R:代表是否按照循环设置中断优先级,1代表循环优先级,0代表固定优先级

循环优先级即原先按照0 1 2 3 4 5 6 7(优先级从高到低)来进行,
但是当0的中断处理完之后,该优先级变为最低优先级,即 1 2 3 4 5 6 7 0,
依此类推,可以用SL来指定最低优先等级

EOI:中断结束命令位,EOI为1,ISR寄存器的相应位会清0,这是8259A主动发送结束终端的做法。(前提是ICW4的AEOI位为0)

  • OCW3

 作用:特殊屏蔽方式和查询方式

 写入端口:主片0x20,从片0xA0


ESMM和SMM:这两位是组合在一起使用的,用来启用或禁用特殊屏蔽模式,ESMM是特殊屏蔽模式的允许位,是个开关。SMM是特殊屏蔽模式位。只有双方都为1,才能进入特殊屏蔽模式。

4~3位:OCW3的标识

P:查询命令,P为1时,设置9259A为中断查询方式,这样就可以通过读取寄存器,来查看中断处理情况

RR:读取寄存器命令,和RIS位一起使用,RR为1才能读取寄存器。

RIS:读取中断寄存器的选择为,选择待读取的寄存器,1则代表选择ISR,0代表选择IRR

  • 8259A又是如何辨别这些寄存器组的呢?

ICW1是从0x20和0xA0写入,ICW要求顺序写入所以没问题。 

OCW1是从0x21和0xA0写入,且OCW2,OCW3有如下表示汇总

 由于OCW1又是在初始化结束后才能使用的,所以初始化结束后第一个写入0x21,0xA0的寄存器即为OCW1。


步骤

8259A 的编程就是写入 ICW OCW

下面总结下写入的步骤。 对于 8259A 的初始化必须最先完成,步骤是:

• 无论 8259A 是否级联, ICW1 和 ICW2 是必须要有的,并且要顺序写入。

• 只有当 ICWl 中的 SNGL 位 1为 时,这表示级联,级联就需要设置主片和从片,这才需要在主片 和从片中各写入 ICW3。 注意, ICW3 的格式在主片和从片中是不同的

• 只能当 ICW1 中的 ICW4 为1时,才需要写入 ICW4 。不过, x86 系统 ICW4 必须为1

在 x86 系统中,对于初始化级联 8259A, 4个 ICW 都需要,初始化单片 8259A, ICW3 不要,其余全要

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值