中断

i.中断

1.     中断定义:中断是一种电信号,由硬件设备生成,并直接送入中断控制器的输入引脚上。再由控制器向处理器发送相应的信号。处理器一经检测此信号,便中断自己当前的工作转而处理中断。处理器通知操作系统已经产生中断,这样操作系统开始对此中断进行适当的处理。

2.     产生中断的原因:Linux内核管理连接到计算机上的硬件设备。由于在处理器和硬件设备相互通信时,处理器的速度往往比外围硬件设备高一个或多个数量级,如果内核让处理器向硬件发送一个请求,等待硬件回应,如果硬件响应很慢,占用处理器不用,浪费资源。

解决办法:内核在硬件响应期间,先处理其他事务,等硬件真正完成请求的操作之后,再回头对它进行处理。方法有两个:轮询和中断。

轮询:内核定期对设备的状态进行查询,然后做出相应的处理。缺点:让内核做很多无用功,因为硬件物理忙碌,完成任务,还是空闲,轮询总是周期性的重复执行。

中断:硬件在需要的时候向内核发出电信号,变内核主动为硬件主动。

3.      中断分类

硬件中断: 从字面上理解就是由硬件(外部设备、或者CPU内部逻辑)产生的中断信号,CPU在捕捉到中断信号后会触发一段固定的逻辑。狭义的理解,硬件中断单指外部 设备,如网卡、硬盘、键盘等产生的中断。在x86体系结构规范中,将这样由外设设备产生的、CPU不可预知的中断定义为“异步中断”。

软件中断:从字面上理解就是由软件、即指令触发的中断,也就是上面提到的由CPU的内部逻辑,比如特定的中断指令、除数为0的除法指令等产生的中断。在x86体系结构规范中,将这样在某一条指令执行完毕后才会产生的中断定义为“同步中断”,也可称之为“异常”。

软中断:原始表述为“softirq",是Linux中断处理机制的一个组成部分。简单地说就是中断产生后(包括硬件中断与软件中断),CPU会执行一段固定的逻辑,这段逻辑的结果就是准备好一些参数并最终跳转到操作系统提供的中断服务中。


ii. 中断处理程序

1.     中断处理程序:在响应一个特点中断的时候,内核会执行一个函数,该函数叫中断处理程序或中断服务例程ISR. 它是被内核调用来响应中断的,运行于中断上下文。

2.     程序特点:中断随时发生,中断处理程序随时可能执行;中断处理程序能快速执行,保证尽可能快地恢复中断代码的执行;即使最精简的中断服务程序,也要与硬件交互,告诉设备中断已被处理。

3.     上半部与下半部产生的原因:中断处理程序又想运行得快,又想完成的工作量多,由于这两个目的不可调和的矛盾,我们一般把中断处理分为上半部和下半部。

4.     上半部:接收到一个中断,立刻执行,但只做有严格时限的工作,如对中断应答或复位硬件,这些工作在禁止中断的情况下完成。

下半部:允许稍后完成的工作在下半部执行,在合适的时机,下半部在开中断的情况下执行。

5.     下半部执行的时机:

a)       内核调用local_bh_enable()函数激活本地CPU的软中断时。

b)       当do_IRQ()完成了I/O中断的处理时或调用irq_exit()宏时

c)       如果系统使用了I/O APIC, 当smp_apic_timer_interupt()函数处理完本地定时器中断时。

d)       多处理器系统中,但CPU处理完CALL_FUNCTION_VECTOR处理器间中断所触发的函数时。

e)       当一个特殊的ksoftirqd/n内核线程被唤醒时。

iii. 注册中断处理程序

中断处理程序是管理硬件的驱动程序的一部分。每一个设备有相关的驱动程序,如果设备使用中断,那么相应的驱动就注册一个中断处理程序。函数如下:


a) 第1个参数irq表示要分配的中断号,获取途径有3种:

1) 固定值

2) 探测获取:probe_irq_off(mask)

3) 编程动态确定: 用request_irq循环注册可能的irq号。

b) 第2个参数是函数指针,指向处理这个中断的实际处理中断程序。

c) 第3个参数是标志的位掩码。

d) 第4个参数是设备的ASCII名字。

e) 第5个参数用于共享中断线,区分共享中断处理程序的多个设备。

PS:此函数可能会睡眠,不能在中断上下文或其他不允许阻塞的代码中使用此函数。因为注册的时候,内核在/proc/irq文件创建一个与中断对应的项。其调用的函数proc_mkdir() 通过proc_create()函数对新的procfs进行设置,而proc_create()调用kmalloc()函数,此函数可能会休眠。

iv. 编写中断处理程序

中断处理程序声明:

static irqreturn_t intr_handler(intirq, void *dev_id, struct pt_regs *regs)

v. 中断处理机制的实现


中断从硬件到内核的路由

 

vi. 中断控制

a) 禁止和激活中断

1) 禁止当前处理器上的本地中断

Local_irq_disable() –>cli指令

Local_irq_enable()àsti指令

2) 禁止中断之前保存中断系统的状态

Local_irq_save(flags);

Local_irq_restore(flags);

Flags不能传递给其他函数,所以这两个函数的调用在同一个函数中。

b) 禁止指定中断线

前面的函数是禁用这个处理器上所有中断的函数。在某种情况下,只禁止整个系统中一条特定的中断线就够了。这就是屏蔽中断。

Void disable_irq(unsigned int irq);

Void disable_irq_nosync(unsignedint irq);

Void enable_irq(unsigned int irq);

Void synchronize_irq(unsigned intirq);

c) 中断系统的状态

In_interrupt(): 如果在中断上下文中,则返回非0,如果在进程上下文中,则返回0

In_irq(): 如果当前正在执行中断处理程序,这返回非0,否则,返回0


你可能感兴趣的:(中断,softirq,tasklet,硬件中断,软中断,软件中断)