Linux内核学习之中断

[中断概述]

中断本质上是一种特殊的电信号,,由硬件设备发向处理器。异常和中断的不同是异常在产生时必须考虑与处理器时钟同步。实际上异常也常常称为同步中断。比如在除0或者缺页时,必须靠内核处理的时候,处理器就会产生一个异常。

[中断处理机制的实现]

中断从硬件到内核的路由

设备产生中断,通过总线把电信号发送给中断控制器。如果中断线是激活的(它们允许被屏蔽的),那么中断控制器就会把中断发往处理器。在大多数体系结构中,这个工作就是通过电信号给处理器的特定管脚发送一个信号。除非在处理器上禁止该中断,否则处理器会立即停止它正在做的事,关闭中断系统,然后跳到内存中预定的位置开始执行那里的代码。这个预定义的位置是由内核设置的,是中断处理程序的入口点。

[中断处理程序]

在响应一个特定中断的时候,内核会执行一个函数,该函数叫做中断处理程序(interrupt handler)也叫做中断服务例程(interrupt service routine)。

中断处理程序就是一个普普通通的C函数,但是它与其他内核函数的真正区别在于,中断处理程序时被内核调用来响应中断的,它运行于中断上下文中。

注册中断处理程序:

static inline int __must_check

request_irq(unsigned int irq, irq_handler_thandler, unsigned long flags,

const char *name, void *dev)

irq:分配的中断号

handler:中断处理函数程序的指针 typedefirqreturn_t (*irq_handler_t)(int, void *);

flags:中断类型

name:与中断相关的设备的名字;

dev:用于共享中断,因为可能在一条中断线上有几个设备,dev用来区分是哪个设备产生的中断

中断上下文和进程上下文对比

中断上下文

进程上下文

定义

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

当程序调用了系统调用或者触发了某个异常,它就陷入了内核空间,此时,内核代表进程执行并处于进程上下文中。

睡眠情况

不可睡眠,不能被调度,也就是说中断上下文中不能使用有可能睡眠的函数

可睡眠,可调度

同步机制

自旋锁

都可

[中断上半部和下半部]

首先问自己一个问题,为什么要把中断分为上半部和下半部,难道一个就放在中断处理程序中不好吗?答案是否定的

1、中断可以随时的打断其他正在执行的程序,如果被打断的代码对系统很重要,那么此时中断处理程序的执行时间应该是越短越好;

2、中断处理程序正在执行时,会屏蔽同条中断线上的中断请求;而更严重的是,如果设置了IRQF_DISABLED,那么该中断服务程序执行时会屏蔽所有其他的中断请求。那么此时应该让中断处理程序执行的越快越好。

上半部:一个快速、异步而简单的处理程序专门来负责对硬件的中断请求做出快速响应,与此同时也要完成那么些对时间要求很严格的操作;

下半部:那么对时间要求相对宽松,其他的剩余工作会在稍后的任意时间执行。

下面是对上半部和下半部的工作划分:

如果一个任务对时间非常敏感,将其放在中断处理程序中执行;

如果一个任务中和硬件相关,将其放在中断处理程序中执行;

如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序执行;

其他所有任务,都应考虑放在下半部执行。

[下半部机制]

软中断

软中断保留给系统中对时间要求最严格以及最重要的下半部使用,目前只有两个子系统(网络和scsi)直接使用软中断。

Tasklet

Tasklet是利用软中断实现的一种下半部机制。在选择使用软中断还是tasklet时,建议使用tasklet,除了网络和SCSI情况。相比软中断,tasklet的接口更简单,锁保护要求较低。

工作队列

工作队列是可以把工作推后交由一个内核线程去执行,下半部总是会在进程上下文中执行,允许重新调度和睡眠。

三种下半部机制对比

下半部

上下文

顺序执行保障

软中断

中断

没有

Tasklet

中断

同类型不能同时执行

工作队列

进程

没有(和进程上下文一样被调度)

切忌贪婪,恨不得一次玩遍所有传说中的好景点,

Linux内核学习之中断

相关文章:

你感兴趣的文章:

标签云: