中断
硬件在需要时候向内核发出信号。
从物理学角度看中断是一种电信号,由硬件产生,并直接送入中断控制器的输入引脚中,中断控制器是一个多路复用的控制器,当从多个引脚之一接收到信号后,会通知处理器,此时处理器会中断当前工作转而处理中断,并且通知操作系统已经产生中断,操作系统运行处理中断的程序。
中断值
中断值通常被称为中断请求(IRQ)线。
特定的中断总要和特定的设备相联系,并且内核要知道这些信息,从而设备发出信息后内核能够分辨出要处理的信息。
中断处理程序
在响应特定中断时,内核会执行一个函数,该函数叫做中断处理程序。
通常来说,一个设备有一个中断处理程序,这是他驱动程序的一部分。
在Linux中,中断处理程序就是普通的c函数,只是使用特定的声明。
中断处理程序运行在中断上下文中,该上下文执行代码不可阻塞。
中断的上半部和下半部
为了让中断运行的快,我们将不紧迫,花费时间多的工作放到下半部处理。
以网卡为例,当网卡接收到数据包存放在自己的缓存中时,通知系统发生中断处理数据包,中断开始执行,将网卡数据包拷贝到操作系统的内存,中断上半部分结束。将控制权返还给操作系统,处理和操作数据包的其他工作在下半部分进行。
中断线可以被多个设备共享,而中断处理程序也可以被多个中断线共享
注册中断处理程序
中断处理程序是设备驱动的组成部分。
驱动程序通过函数request_irq()来注册中断程序,并且激活中断请求线。
中断线是共享的,则一个中断会发生很多中断处理程序的执行。
驱动给设备分配一条给定的中断线:
int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char* name,
void *dev);
参数一:中断号
参数二:中断处理函数指针
参数三:中断处理标志(IRQF_DISABLED:内核在处理这个中断时,要终止其他所有中断;IRQF_SHARD:多个中断处理程序之间共享中断线)
参数四:中断设备的名字(eg.“keyboard")
参数五:共享中断线,用来区分不同的设备,如果无需共享为NULL
编写中断处理程序
irqreturn_t intr_handler(int irq,void *dev);dev用来区分处理中断线的设备(多设备处理一中断的情况下)
Linux的中断处理程序是不可重入的,即如果中断处理程序正在执行中断a时发生了中断a,系统会忽略。
但是除了中断a的中断都是可以处理的。
中断上下文
在进程上下文中可以通过current宏获得正在执行的进程的pcb,所以可以睡眠。
而中断上下文不能重新找到上下文,所以不能睡眠。
中断上下文的栈是一页。同时内核栈也是一页。
中断处理机制的实现
设备硬件产生一个中断,发送给中断控制器,中断控制器发送给处理器,处理器跳到do_IRQ()函数的位置执行,判断该线上是否有中断处理程序,如果有则运行所有的中断处理程序,返回内核中断的代码。