【Linxu内核设计与实现】-第7章 中断和中断处理

时间:2022-06-20 16:54:42

第7章 中断和中断处理

操作系统的核心任务之一-对连接上的硬件进行管理(硬盘、键盘、鼠标等)。要想管理这些硬件,就需要可以和他们进行通信。硬件的反应要远远慢于CPU,轮询会耗费大量CPU资源,显然不适合,那就是通过中断机制来实现。


7.1 中断

(1)中断本质上是一种特殊的电信号。由硬件设备发向处理器。

(2)中断随时可产生,内核随时可能被到来的中断所打断。

(3)每个中断都有唯一的数字标识,操作系统得以对中断进行区分。

(4)硬件发出的中断是为了引起内核的关注,“嗨,我有新的按键需要处理,读取并处理这些操作把”。

(5)异常:异常与中断不同,异常产生时必须与处理器时钟同步。异常也常常称为同步中断。

(6)系统调用是一种异常,来进入内核。

(7)中断是由硬件引起的,而不是软件。


7.2 中断处理程序

(1)在响应一个中断的时候,内核会执行中断处理程序,或者称为中断服务程序。

(2)产生中断的每个设备都有一个相应的中断处理程序。

(3)一个设备的中断处理程序,是它设备驱动程序的一部分。设备驱动程序是用于对设备管理的内核代码。

(4)Linux中,设备驱动程序是C函数而已,只是需要按照特定的类型声明。

(5)中断处理程序是被内核调用来响应中断的,运行于中断上下文的特殊上下文中(该上下文代码不可被阻塞)。

(6)中断随时发生,中断服务程序随时可能被执行,因此需要保证中断处理程序可以快速执行。

(7)中断服务程序需要告诉硬件,我听到你了,现在回去工作吧。即需要对硬件应答,同时可能需要进行数据拷贝等操作。如网络设备中断。


7.3 上半部与下半部对比

(1)中断处理为了执行快,而且可执行的内容多,因此被分为上半部和下半部

(2)

  • 上半部:中断处理程序,接收一个中断,它就立刻开始执行,只做有严格时限的工作,例如对接受的中断进行硬件应答或者复位硬件。
  • 下半部:允许稍后完成的工作。Linux提供了实现下半部的各种机制。

(3)网卡例子

上半部:

       网卡发出中断:hi内核,我有数据来了。内核执行网卡中断处理程序来做出应答。拷贝最新网络数据包到内存中,因为网卡缓存有限,不及时拷贝,数据可能丢失,拷贝后上半部分完成。

下半部:

       处理和操作数据包。


7.4 注册中断处理程序

(1)中断处理程序是驱动程序的组成部分。驱动程序可以通过request_irq()函数注册一个中断处理程序。并且激活给定的中断线,以处理中断。

(2)request_irq()在<linux/interrupt.h>中

int request_irq(unsignedint irq,irq_handler_t handler,unsigned long flags,const char * name,void *dev)
参数解析:

  • 第一个参数irq:

要分配的中断号。

  • 第二个参数handler:

是一个指针,指向处理这个中断的中断处理程序。只有操作系统一接受到中断,这个函数就会被调用。

7.4.1 中断处理程序标志

  • 第三个参数flags:

可以是0,也可以是一个或多个标志的位掩码<linux/interrupt.h>。

【Linxu内核设计与实现】-第7章 中断和中断处理

  • 第四个参数name:

与中断相关的设备的ASCII文本表示,这些名字会被/proc/irq和/proc/interrupts文件使用,以便与用户通讯。

  • 第五个参数dev:

用于共享中短线,如果无需共享中断线,那么该参数设置成NULL即可。当中断处理程序需要释放的时候,dev将提供唯一的标识信息(cookie),以便从共享中断线诸多中断处理程序中删除指定的哪一个。

  • 返回值:

执行成功返回:0。非零则失败。

注意:

request_irq()函数可能休眠,不能在中断上下文或其他不允许阻塞的代码中调用,由于kmalloc()可能休眠。

7.4.2 一个中断例子

【Linxu内核设计与实现】-第7章 中断和中断处理

7.4.3 释放中断处理程序

(1)卸载驱动的时候,需要注销相应的中断线。调用

Void free_irq(unsigned int irq , void *dev)
(2)如果中断线不是共享的,该函数删除处理程序的同时,将禁用这条中断线。如果是共享的,则仅删除dev对应的处理程序,中断线只有在删除了最后一个处理程序时才被禁止。

【Linxu内核设计与实现】-第7章 中断和中断处理

7.5 编写中断处理程序

中断处理程序函数声明

static irqreturn_t intr_handler(int irq,void *dev)

  • 参数irq:中断号
  • 参数dev:通用指针,与传递给request_irq()的dev一致。可以用来区分共享同一中断处理程序的多个设备。
  • 返回值irqreturn_t:实际为一个int。中断处理程序被正常调用,且确实是它所对应设备产生中断时返回IRQ_HANDLER。

7.6 中断上下文

(1)当执行一个中断处理程序时,内核处于中断上下文中。

(2)中断上下文不可以休眠,具有较为严格的时间限制。

(3)回忆:进程上下文是一种内核所处的操作模式,此时内核代表进程执行,如执行系统调用或者运行内核线程,进程上下文可以休眠,也可以调用调度程序。

(4)中断处理程序尽可能的迅速,简洁,尽可能把工作从中断处理程序中独立出来,放在下半部执行,因为下半部可以在更适合的时间执行。


7.7 中断处理机制的实现(待深入)

(1)中断处理系统在Linux中的实现非常依赖于体系结构

【Linxu内核设计与实现】-第7章 中断和中断处理

【Linxu内核设计与实现】-第7章 中断和中断处理


7.8 /proc/interrupts

(1)procfs是一个虚拟文件系统,只存在于内核内存中,一般安装与/proc目录。

(2)/proc/interrupts中存放了系统中与中断相关的统计信息。

【Linxu内核设计与实现】-第7章 中断和中断处理


7.9 中断控制

【Linxu内核设计与实现】-第7章 中断和中断处理

7.9.1 禁止和激活中断

(1)用于禁止和激活当前处理器上的本地中断。

7.9.2 禁止指定中断线

(1)仅禁止整个系统中的某一条中断线。

7.9.3 中断系统的状态

(1)获取中断系统的状态(禁止or激活),是否处于中断上下文的执行状态。

(2)中断控制方法列表

【Linxu内核设计与实现】-第7章 中断和中断处理


7.10 小结

中断是一种由设备使用的硬件资源异步的向处理器发信号,中断就是由硬件来打断操作系统。

【Linxu内核设计与实现】-第7章 中断和中断处理