这篇文章是《读薄「Linux 内核设计与实现」》系列文章的第 IV 篇,本文主要讲了以下问题:中断和中断处理程序的概念与实现原理、Linux 中的下半部以及内核同步方法。
0x00 中断和中断处理程序
I 中断
中断是一种特殊的电信号,由硬件发向处理器,处理器接收到中断时,会马上箱操作系统反映,由操作系统进行处理。中断随时可以产生,因此,内核随时可能因为新到来的中断而被打断。
不同的设备对应的中断不同,每个中断通过一个唯一的数字标识,这些中断值通常被称为中断请求(IRQ)线。
II 中断处理程序
中断处理程序又成为中断处理例程(ISR),是内核在响应中断时执行的一个函数
一个中断处理程序对应一个中断,一个设备可能发出多种中断
对于外部设备,中断处理程序是设备驱动程序的一部分
在 Linux 中,中断处理程序和 C 函数区别不大,但有自己的规范,主要是运行时需要在中断上下文中
0x01 中断处理机制
I 注册中断处理程序
驱动程序可以通过request_irq()
函数注册一个中断处理程序(linux/interrupt.h)
int request_irq(unsigned int irq,
irqhandler_t handler,
unsigined long falgs,
const char *name,
void *dev)
irq:
表示要分配的中断号handler:
一个指针,指向处理这个中断的实际中断处理函数
typedef irqhandler_t(*irq_handler_t)(int, void*);
II 释放中断处理程序
卸载驱动程序时,需要注销响应中断处理程序,并释放中断线。
void free_irq(unsigned int irq, void *dev);
如果指定的中断线不是共享的,那么该函数删除处理程序的同时将禁用这条中断线;中断线是共享的,则仅仅删除 dev 对应的处理程序,而这条中断线本身只有在删除了最后一个处理程序时才会被禁用
III 中断的禁止与激活
local_irq_disable();
local_irq_enable();
IV 上半部与下半部
又想中断处理程序运行的快,又想中断处理程序完成的工作多,这两个目的显然有所抵触,所以把中断处理分为两个部分:
中断处理程序是上半部,接收到一个中断,它就立刻开始执行,但只做有严格时