中断机制让硬件在需要的时候再向内核发出信号。
7.1中断
概念:使得硬件得以发出通知给处理器
产生时机:随时可以产生,内核随时可能因为新到来的中断而被打断
流程:当接收到一个中断后,中断控制器会给处理器发送一个电信号。处理器一检测到此信号,便中断自己的当前工作转而处理中断。伺候,处理器通知操作系统已经产生中断,这样,操作系统就可以对这个中断进行适当地处理了。
中断标志:不同设备对应的中断不同,每个中断都有一个唯一的数字标志。因此,来自键盘的中断有别于来自硬盘的中断,从而使得操作系统能够对中断进行区分,并指导是哪个硬件设备产生了哪个中断。这些中断值通常被称为中断请求线。
与异常的区别:
●异常在产生时必须考虑与处理器时钟同步。实际上,异常也常常称为同步中断。
●工作方式类似,中断是由硬件引起,异常是由软件引起。
7.2 中断处理程序
概念
当响应一个特定中断的时候,内核会执行一个函数,该函数叫作中断处理程序。
与普通函数区别
在Linux中,中断处理程序就是普通的C函数。只不过这些函数必须按照特定的类型声明,以便内核能够以标准的方式传递处理程序的信息。
中断处理程序是被内核调用来响应中断的,它们运行于中断上下文的特殊上下文中,又称为原子上下文,该上下文中的执行代码不可阻塞。
特点
中断可能随时发生,因此中断处理程序随时可能执行。所以必须保证中断处理程序能够快速执行,这样才能保证尽可能快地恢复中断代码的执行。
中断处理程序的工作量可能也很大,像如今的千兆比特和万兆比特以太网卡。
7.3 上半部与下半部的对比
两部分的原因
又想中断处理程序运行得快,又想中断处理程序完成的工作量多,这两个目的有所矛盾。所以把中断处理切为两个部分或两半。
两部分
●上半部:
中断处理程序,接收到一个中断就立即开始执行,但只做有严格时限的工作。例如对接收的中断进行应答或复位硬件,这些工作都是在所有中断被禁止的情况下完成。能够被允许稍后完成的工作会推迟到下半部去。
●下半部:
合适的时机,下半部会被开中断执行。
举例:
7.4 注册中断处理程序
具体见书
驱动程序可以通过request_irq()函数注册一个中断处理程序,并且激活给定的中断线,以处理中断。
int request_irq(unsigned int irq, //要分配的中断号
irq_handler_t handler, //指针,指向实际中断处理程序
unsigned long flags, //标志位,可以设置模式
const char *name, //中断相关设备的ASCII文本表示
void *dev) //共享中断线
7.5 编写中断处理程序
见书
7.6 中断上下文
进程上下文可以睡眠,也可以调用调度程序。
中断上下文不可以睡眠,因为没有后备进程,所以 中断处理程序不能调用睡眠的函数。
时间限制中断上下文具有较为严格的时间限制,因为它打断了其它代码,所以中断上下文应当迅速、简洁。
中断处理程序栈
曾经中断处理程序并不具有自己的栈,它们共享所中断的进程的内核栈,内核栈的大小为两页。
2.6版本后,将栈的大小从两页减到一页,为了应对栈大小的减少,中断处理程序拥有了自己的栈,每个处理器一个,大小为一页。称为中断栈。
7.7 中断处理机制的实现
7.8 /proc/interrupts
procfs是一个虚拟文件系统,它只存在于内核内存,一般安装于/proc目录。在procfs中读写文件都有调用内核函数。
7.9 中断控制
Linux内核提供了一组接口用于操作机器上的中断状态。这些接口为我们提供了能够进制当前处理器的中断系统,或屏蔽掉整个机器的一条中断线的能力。
控制中断系统的原因归根结底是需要提供同步。通过禁止中断,可以确保某个中断处理程序不会抢占当前的代码。