目录
一、概述
操作系统需要对硬件外设进行管理,但是二者的处理速度往往不在一个数量级上,需要一种方法是CPU和外设协同工作而不至于影响到机器的性能,如果采用轮询——内核周期性的对设备状态进行查询,这样会浪费不少CPU时间,从而考虑硬件再需要时再通知内核,变被动为主动,这就是中断机制的由来。
二、中断的框架
2.1 硬件示意图
以8259A为基本模型,主要为了说明中断整体流程
外设的中断信号线通常通过中断控制器与CPU相连,通过上图简单的PIC(8259A)框图试图说明基本的中断硬件框架和处理流程。在PIC工作之前,通常要对其进行配置,主要包括
- 设定中断触发电信号的类型,常见的有水平触发和边沿触发。
- 将外设的中断引脚号映射到处理器可见的中断vector。
- 屏蔽掉某些外部设备的中断。
PIC通常提供一些控制寄存器来进行上述工作,如上图中的ICWs。一个重要的功能就是配置映射规则(红色部分),这样OS通过软件中断号irq来标识中断,软件上拥有更大的灵活性。
2.2 中断处理流程
2.2.1 中断处理过程中典型的寄存器
IRR 中断请求寄存器,某管脚收到中断请求但还没有提交给CPU,概念上等同于有些架构上的中断pending寄存器。
IMR 中断屏蔽寄存器,屏蔽某一个管脚的中断,这样IRR就不会感知到中断。
PR 中断优先级寄存器。
ISR 中断处理中,中断已经提交给CPU但CPU没有处理完毕。
2.2.2 PIC中断处理流程
- 一个或者多个管脚上产生中断,如果中断没有被屏蔽,IRR相应位置位。
- PIC 拉高INT 通知CPU有中断发生。
- CPU 通过INTA 应答。
- 收到应答,对应的IRR位清0,对应的ISR置1。
- CPU通过INTA发送二次脉冲,计算优先级最高的IRQ,通过D0~D7将其对应的vector发送给CPU。
- 等待CPU写EOI,清除ISR对应的位。
TIPS:
- 被IMR屏蔽的寄存器,不会在IRR中置位,可能会导致中断丢失。
- CPU 自身屏蔽中断时,如x86上的(CLI),中断会在IRR中置位,处于pending状态,一旦cpu开启中断使能,会立即处理。
画了个图,便于记忆
2.2.3 CPU侧中断处理流程
先说明一个中断向量表的概念,当处理器被中断打断以后会暂停当前的工作,处理中断,这时候需要知道到哪里获取中断处理函数的地址,中断向量表每一项都是处理地址,使用vector去定位这个地址。
- cpu获取到vector,查询中断向量表,获取中断处理地址。在x86上根据vector获取IDT表中的中断门,这里需要留意的是程序通过中断门跳转后,对应EFLAGS中的中断使能位IF会关闭!
- 保存被打断任务的上下文,执行中断处理程序。
- 中断完成后写EOI寄存器应答,恢复被打断的任务的上下文,使其继续执行。
TIPS:
- 中断处理程序运行在中断上下文,一般和进程上下文进行区分。简单说,上下文是指程序运行时寄存器的最小合集。进程上下文是在进程切换(睡眠、调度等)时需要保存的寄存器的集合,此时内核代表进程执行(系统调用或内核线程);中断上下文是中断打断当前执行的任务过程而产生的,在切换过程中,中断切换的上下文和进程切换的上下文是不同的(如进程调度时需要切换页表cr3,中断切换则不需要)。因此,在进程上下文中可以执行的睡眠、调度等操作不能在中断上下文中进行(因为切换过程要保存原有上下文,切换新的上下文,而切换是由硬件和软件协同完成的,两者上下文不一致会导致问题),后面研究一下不同上下文切换过程就会明白。
- 在中断上下文执行代码不可阻塞
三、中断的上半部和下半部
3.1 上半部和下半部的由来
一方面,由于中断是打断了原有执行流程的异步操作,我们希望它能迅速的执行完毕返回到原有的任务中去,因为硬件在进入中断上下文过程中中断是被自动关闭的(还记得上面x86执行中断门IF被关闭吗),我们必须尽快开启中断响应其他事件。另一方面,中断处理程序又需要完成大量的工作,如在处理网卡数据包时,处理程序既要对硬件进行应答,还要将数据包拷贝到内存中,交给协议栈处理,这针对千兆万兆的网卡是极大的工作量。显然这两个方面是矛盾的,因此我们一般把中断切分为两个部分:上半部(top half)和下半部(bottom half)。上半部中断是关闭的(即不会主动打开中断),主要完成一些重要、紧急的与硬件相关的任务,还是以网卡举例,上半部会会ack nic保证nic可以触发中断,将报文拷贝到ram中,打开中断,发送EOI。后续协议栈处理交由下半部来做。
四、小结
TO DO
还是没有把所有的展示出来,以后补充
五、参考
【1】深入Linux设备驱动程序内核机制 陈学松
【2】系统虚拟化——原理与实现 intel
【3】Linux内核设计与实现 Robert Love
【4】 linux kernel的中断子系统之(八):softirq