Linux内核完全注释(20周年版·第2版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2 Linux中断机制

在使用80x86组成的PC中,采用了两片8259A可编程中断控制芯片。每片可以管理8个中断源。通过多片的级联方式,能构成最多管理64个中断向量的系统。在P C/AT系列兼容机中,使用了两片8259A芯片,共可管理15级中断向量。其级联示意图见图2-5。其中从芯片的INT引脚连接到主芯片的IR2引脚上。主8259A芯片的端口基地址是0x20,从8259A芯片是0xA0。

图2-5 PC/AT微机级联式8259控制系统

在总线控制器控制下,8259A芯片可以处于编程状态和操作状态。编程状态是CPU使用IN或OUT指令对8259A芯片进行初始化编程的状态。一旦完成了初始化编程,芯片即进入操作状态,此时芯片即可随时响应外部设备提出的中断请求(IRQ0~IRQ15)。通过中断判优选择,芯片将选中当前最高优先级的中断请求作为中断服务对象,并通过CPU引脚INT通知CPU外中断请求的到来,CPU响应后,芯片从数据总线D7~D0将编程设定的当前服务对象的中断号送出,CPU由此获取对应的中断向量值,并执行中断服务程序。

对于Linux内核来说,中断信号通常分为两类:硬件中断和软件中断(异常)。每个中断是由0~255之间的一个数字来标识。对于中断int0~int31(0x00~0x1f),每个中断的功能由Intel公司固定设定或保留用,属于软件中断,但Intel公司称之为异常。因为这些中断是在CPU执行指令时探测到异常情况而引起的。通常还可分为故障(fault)和陷阱(traps)两类。中断int32~int255(0x20~0xff)可以由用户自己设定。在Linux系统中,则将int32~int47(0x20~0x2f)对应于8259A中断控制芯片发出的硬件中断请求信号IRQ0~IRQ15,并把程序编程发出的系统调用(system_call)中断设置为int128(0x80)。

在Linux 0.11内核源代码的head.s程序中,内核首先使用一个哑中断向量(中断描述符)对中断描述符表(Interrupt Descriptor Table,IDT)中所有256个描述符进行了默认设置(boot/head.s,78行)。这个哑中断向量指向一个默认的“无中断”处理过程(boot/head.s,150行)。当发生了一个中断而又没有重新设置过该中断向量时就会显示信息“未知中断(unknown in-terrupt)”。因此,对于系统需要使用的一些中断,内核必须在其继续初始化的处理过程中(init/main.c)重新设置这些中断的中断描述符项,让它们指向对应的实际处理过程。通常,硬件异常中断处理过程(int0~int 31)都在traps.c的初始化函数中进行了重新设置(kernel/traps.c,181行),而系统调用中断int128则在调度程序初始化函数中进行了重新设置(kernel/sched.c,385行)。