1. 中断
本质是一种特殊的电信号,由硬件发给处理器,处理器向OS反映信号到来,然后处理信号。
中断需要有唯一标识以区分,这样OS才能执行对应的中断处理程序。
中断不需考虑与处理器时钟同步,可随时产生,内核可被新来的中断而打断。
异常:要考虑与处理器时钟同步,因此叫同步中断(如除以0,缺页等),处理方式和处理中断类似。
如系统调用处理程序异常,通过软中断
int 0x80
指令实现。
2. 中断处理程序
每种中断对应一个中断处理程序(Interrupt handler),在Linux中就是普通的C函数,但要按照特定的类型声明。
上下文:处于中断上下文(原子上下文)中,执行的代码不可阻塞。
3. 上半部与下半部
把中断处理切成2个部分:
- 上半部:即中断处理程序,接收中断,立刻执行,不过工作要有严格时限
- 下半部:允许稍后完成的工作推到这里运行(如处理数据等)
4. 注册与实现中断处理程序
中断处理程序是驱动程序的一部分,需要向内核注册,调用request_irq()
函数。该函数可能会阻塞,因此不能再中断上下文或其它不允许阻塞的地方使用。
request_irq() --> proc_mkdir() create /proc/irq/xx --> proc_create() --> kmalloc() sleep here
。
卸载时,调用free_irq()
释放中断线。
实现时,需要声明为类似的签名:static irqreturn_t xx_handler(int irq, void* dev)
。
实现时不考虑重入,因为中断正在执行时,对应中断线在所有处理器上都会被屏蔽,防止同一中断线线上接收另一个新中断。
5. 中断上下文
中断处理程序运行时,进入中断上下文。
关于中断上下文:
current
无意义(虽然指向被中断的进程)- 不可以睡眠或放弃CPU,时间限制严格
- 不能占用互斥体
- 不能访问用户虚拟内存空间
- 不可重入
- 能被更高等级的IRQ中断
- 处理程序要尽量简洁迅速,尽量把复杂工作放入下半部
6. 中断处理机制的实现
流程是:
- 设备产生中断,传给中断控制器
- 若中断线是被激活的,则将中断发给处理器
- 处理器停止正在做的事情,关闭中断系统,跳转到一个预定义中断程序的入口(根据中断线,得到IRQ号,然后可跳转到对应的中断处理程序)
- 判断中断线上有没有对应的中断处理程序,且没有正在运行,若有,运行中断处理程序
- 从中断代码返回,恢复
7. /proc/interrupts
procfs:一个虚拟的文件系统,只存于内核内存,一般挂载在/proc
下。对于该文件系统下的读写都要调用内核函数,模拟真实文件的读写。
/proc/interrupts
:存放系统中断的统计信息(包括中断线、中断在不同CPU核心的计数、对应的设备等)
8. 中断控制
Linux提供一组接口,能让我们禁止系统的中断系统,或屏蔽某条中断线,定义可在<asm/system.h>
和<asm/irq.h>
找到。