系统 - 中断

一 中断概念

1、中断

  所谓中断,是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。
  其实从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如 8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。
  中断控制的主要优点是只有在IO接口需要服务时才去响应它,使得CPU很淡定的做它自己的事情,只有IO口有需求的时候才去响应它。同时中断中也设计了中断优先级,来处理一些很紧急的事件。

2、中断向量

  在Intel X86中可以支持256中向量中断,为了使处理器能使别每种中断源,给它们进行了编号,叫做中断向量。在Linux中,编号0~31的向量对应于异常和非屏蔽中断;编号32~47的向量(即由IO设备引起的中断)分配给屏蔽中断;编号48~255的向量用来标示软中断。Linux用其中的128或0x80来实现系统调用;非屏蔽中断的向量和异常的向量是固定的。

3、异常和中断的区别

  异常:是指CPU内部出现的中断,即在CPU执行特定指令时出现的非法情况。同时异常也称为同步中断,因此只有在一条指令执行后才会发出中断 ,不可能在指令执行期间发生异常。
  产生的原因:程序的错误产生的,内核必须处理的异常条件产生的;异常又分为故障和陷阱,它们都不使用中断控制器,也不能被屏蔽;X86处理处理器中大约有20种异常,Linux内核必须为每种异常提供一个专门的异常处理程序。
  中断:也称为异步中断。因此它是由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能在指令之间发生。中断又分为外部可屏蔽中断(INTR)和外部非屏蔽中断(NMI);所用IO设备产生的中断请求均引起可屏蔽中断,硬件故障引起的故障则产生非屏蔽中断。

4、中断处理程序

  在响应一个特定中断的时候,内核会执行一个函数,该函数叫中断处理程序(interrupt handler)或中断服务例程(interrupt service routine,ISR)。产生中断的每个设备都有一个相应的中断处理程序。一个设备的中断处理程序是它设备驱动程序的一部分。中断处理程序与其他内核的真正区别在于:中断处理程序是被内核调用来响应中断的,而它们运行于我们称之为中断上下文的特殊上下文中。

5、中断控制器

  在X86计算机的 CPU 为中断只提供了两条外接引脚:NMI 和 INTR。NMI 是不可屏蔽中断,它通常用于电源掉电和物理存储器奇偶校验;INTR是可屏蔽中断,可以通过设置中断屏蔽位来进行中断屏蔽,它主要用于接受外部硬件的中断信号,这些信号由中断控制器传递给 CPU。目前常见的中断控制器有可编程中断控制器8259A和高级可编程中断控制器(APIC)。那么我们如何知道我们机子上使用的是那种中断控制器呢?通过在终端出入命令:cat /proc/interrupts来查看!

二 中断描述符表

1、引入

  在实地址模式中,CPU把内存中从0开始的1kb空间作为一个中断向量表。表中的每个表项占四个字节,由两个字节的段地址和两个字节的偏移量组成,这样构成的地址就是相应中断处理程序的入口地址。
  在保护模式下,中断向量表中的表项由8个字节组成。此时他也有了新的名字:中断描述表(Interrupt Descriptor Table,IDT),其中的每个表项叫做一个门描述符(great descriptor)。“门”的含义是当中断发生时必须先通过这些门,然后才能进入相应的处理程序。

2、任务门(Task gate)

  其类型码为101,门中包含了一个进程的TSS 段选择符,但偏移量部分没有使用,因为TSS本身是作为一个段来对待的,因此,任务门不包含某一个入口函数的地址。TSS 是Intel 所提供的任务切换机制,但是 Linux 并没有采用任务门来进行任务切换。

3、中断门(Interrupt gate)

  其类型码为110,中断门包含了一个中断或异常处理程序所在段的选择符和段内偏移量。当控制权通过中断门进入中断处理程序时,处理器清IF 标志,即关中断,以避免嵌套中断的发生。中断门中的DPL(Descriptor Privilege Level)为0,因此,用户态的进程不能访问Intel 的中断门。所有的中断处理程序都由中断门激活,并全部限制在内核态。

4、陷阱门(Trap gate)

  其类型码为111,与中断门类似,其唯一的区别是,控制权通过陷阱门进入处理程序时维持IF 标志位不变,也就是说,不关中断。

5、系统(调用)门(System gate)

  这是Linux 内核特别设置的,用来让用户态的进程访问Intel 的陷阱门,因此,门描述符的DPL 为3。通过系统门来激活4 个Linux 异常处理程序,它们的向量是3、4、5 及128,也就是说,在用户态下,可以使用int 3、into、bound 及int 0x80 四条汇编指令。
  最后,在保护模式下,中断描述符表在内存的位置不再限于从地址0 开始的地方,而是可以放在内存的任何地方。为此,CPU 中增设了一个中断描述符表寄存器IDTR,用来存放中断描述符表在内存的起始地址。中断描述符表寄存器IDTR 是一个48 位的寄存器,其低16位保存中断描述符表的大小,高32 位保存IDT 的基址,如图3.3 所示

  Linux 内核在系统的初始化阶段要进行大量的初始化工作,其与中断相关的工作有:初始化可编程控制器8259A;将中断向量IDT 表的起始地址装入IDTR 寄存器,并初始化表中的每一项。
  用户进程可以通过INT 指令发出一个中断请求,其中断请求向量在0~255 之间。为了防止用户使用INT 指令模拟非法的中断和异常,必须对IDT 表进行谨慎的初始化。其措施之一就是将中断门或陷阱门中的DPL 域置为0。如果用户进程确实发出了这样一个中断请求,CPU 会检查出其CPL(3)与DPL(0)有冲突,因此产生一个“通用保护”异常。
  但是,有时候必须让用户进程能够使用内核所提供的功能(比如系统调用),也就是说从用户空间进入内核空间,这可以通过把中断门或陷阱门的DPL 域置为3 来达到。

三 中断处理过程

  当CPU 执行了当前指令之后,CS 和EIP 这对寄存器中所包含的内容就是下一条将要执行指令的逻辑地址。在对下一条指令执行前,CPU 先要判断在执行当前指令的过程中是否发生了中断或异常。如果发生了一个中断或异常,那么CPU 将做以下事情。

  1. 确定所发生中断或异常的向量 i(在0~255 之间)。
  2. 通过IDTR 寄存器找到IDT 表,读取IDT 表第 i 项(或叫第i 个门)。
  3. 分两步进行有效性检查:首先是“段”级检查,将CPU 的当前特权级CPL(存放在CS寄存器的最低两位)与IDT 中第 i 项中的段选择符中的RPL 相比较,如果RPL(3)大于CPL(0),就产生一个“通用保护”异常(中断向量13),因为中断处理程序的特权级不能低于引起中断的程序的特权级。这种情况发生的可能性不大,因为中断处理程序一般运行在内核态,其特权级为0。然后是“门”级检查,把CPL 与IDT 中第 i 个门的DPL 相比较,如果CPL (3)大于DPL(0),CPU 就不能“穿过”这个门,于是产生一个“通用保护”异常,这是为了避免用户应用程序访问特殊的陷阱门或中断门。但是请注意,这种检查是针对一般的用户程序引起的中断(INT 指令),而不包括外部I/O 产生的中断或因CPU内部异常而产生的异常,也就是说,如果产生了中断或异常,就免去了“门”级检查。
  4. 检查是否发生了特权级的变化。若中断发生时CPU运行在用户空间,而中断处理程序运行在内核态,特权级发生了变化,所以会引起堆栈的更换。也就是说,从用户堆栈切换到内核堆栈。而当中断发生在内核态时,即CPU 在内核中运行时,则不会更换堆栈。
  5. CS : EIP 的值就是IDT 表中第i 项门描述符的段选择符和偏移量的值,此时,CPU 就跳转到了中断或异常处理程序。

四 硬中断和软中断

1、中断上半部分与中断下半部分

  中断处理可以分为两部分:中断处理工作,例如对接收中断进行中断或复位硬件,这些工作都在所有中断被禁止的情况下完成。可以稍后完成的工作推迟到下半部,在合适的情况下执行下半部分中断。例如:
  当网卡接收流入网络的数据包时,需要通知内核数据包到了,网卡需要立即完成这件事,从而优化网络的吞吐量和传输周期,以避免超时。因此网卡立即发出中断,通知内核这里有最新的数据包。内核通过执行网卡已注册的中断处理程序作出应答。中断开始运行,应答硬件,复制最新的网络数据包到内存,这些都是重要的、紧迫的、又与硬件相关的的工作。处理和操作其他数据包的其他工作在随后的下半部分进行。
  中断下半部:下半部分执行的任务是执行与中断处理密切相关,但中断处理程序本身不执行的工作。和上半部分只能通过中断处理程序实现不同,下半部分可以通过多种机制实现。一般硬中断基本为中断的上半部分,软中断和tasklet是中断的下半部分,将上半部分没有实现完的处理继续执行。

2、硬中断

  1. 硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)。
  2. 处理中断的驱动是需要运行在CPU上的,因此,当中断产生的时候,CPU会中断当前正在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU(也有一种特殊的情况,就是在大型主机上是有硬件通道的,它可以在没有主CPU的支持下,可以同时处理多个中断。)。
  3. 硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些时间去处理的进程,中断代码本身也可以被其他的硬中断中断。
  4. 对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。

3、软中断

  1. 软中断的处理非常像硬中断。然而,它们仅仅是由当前正在运行的进程所产生的。
  2. 通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。
  3. 软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度。一些内核允许设备驱动的一些部分存在于用户空间,并且当需要的时候内核也会调度这个进程去运行。
  4. 软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值