Chinaunix首页 | 论坛 | 博客
  • 博客访问: 567267
  • 博文数量: 213
  • 博客积分: 6789
  • 博客等级: 准将
  • 技术积分: 1947
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-01 17:11
文章分类

全部博文(213)

文章存档

2012年(9)

2011年(62)

2010年(99)

2009年(43)

分类: LINUX

2010-05-05 14:50:16

中断机制:变内核主动为硬件主动。
中断
中断使得硬件得以与处理器进行通信。中断本质上是一种特殊的电信号,由硬件设备发向处理器。处理器接受到中断后,会马上向操作系统反映此信号的到来,然后就由OS负责处理这些新到来的数据。硬件设备声称中断的时候不考虑与处理器同步,因为中断在任何时候都会发生。

不同的中断对应不同的中断号, 每个中断都有唯一的数字标识。这些中断值通常被称为中断请求线。
异常
异常与中断不同,异常与系统时钟同步,也称为同步中断。为什么要提及异常,因为许多处理器在处理异常时候的方法与处理中断时候是很类似的。
中断处理程序
在响应一个中断的时候,内核会执行一个函数,这个函数就是中断处理程序。这个程序是与中断相联系的,一个设备可以有多个中断,一个中断对应一个处理程序。中断处理函数与普通C函数几乎没有区别,只不过这些函数都要按照特定的类声明。中断处理程序于其他内核函数的真正区别在于:中断处理程序是被内核调用来响应中断,而他们运行于我们称之为中断上下文中。
上半部与下半部的对比
既想让程序运行的快,又想让程序完成很多事情,鉴于这2个目的之间存在不可调和的矛盾,我们把中断分为上半部和下半部。上半部,接收到一个中断,它就立即执行,但只作有严格时限的工作,例如对接收的中断进行应答或复位硬件,这些工作都是在所有中断被禁止的情况下完成的。能够允许稍后执行的工作都留在下半部分执行。
注册中断处理程序
int request_irq(unsigned int irq, irqreturn_t(*handler)(int, void *, struct pt_regs *),
                unsigned long irqflags, const char * devname, void *dev_id)
第一个参数irq,表示要分配的中断号。
第二个参数handler是一个指针,指向处理这个中断的实际中断处理程序。
第三个参数irqflag, 可以为0, 也可以是下面中的一个
SA_INTERRUPT: 表明给的的中断为快速中断处理程序。这个标记在现在表示快速中断成立在禁止所有中断下运行。而没有这个标记下,只是禁止当前中断线。
SA_SAMPLE_RANDOM: 此标志表明这个设备产生的中断对内核熵池有贡献。
SA_SHIRQ: 表示可以在多个中断处理程序之间共享中断线。
第四个参数devname是与中断相关的设备的ASCII文本表示法。
第五个参数dev_id主要用于共享中断线。当一个中断处理程序需要释放时,dev_id将提供唯一的标志信息,以便从共享中断线的许多中断处理程序中找出要释放的。
request_irq()成功执行会返回0, 这个函数可能会睡眠, 所以,不能在中断上下文或者其他不允许阻塞的代码中调用该函数。
释放中断处理程序
在卸载驱动时候,需要注销相应的中断处理程序,并释放中断线。可以调用void *free_irq(unsigned int irq, void *dev_id)来释放中断线。
编写中断处理程序
static irqreturn_t intr_handler(int irq, void *dev_id, struct pt_regs *regs)
第一个参数已经没有用了。
第二个参数dev_id是一个通用指针,它在与中断处理程序注册时传递给request_irq()的参数dev_id必须一致。
第三个参数,调试时候才用到,现在已经用的很少了。
当中断处理程序检测到一个中断,但该中断对应的设备并不是在注册处理函数期间指定的产生源时,返回IRQ_NONE;当中断处理函数正确调用,并且确实是所对应的设备产生了中断,返回IRQ_HANDLED。
中断处理程序一般都标记为static,因为它从来不会被别的文件中的代码直接调用。
重入和中断处理程序
linux中断无须重入,当一个给定的中断处理程序正在执行时,相应的中断线在所有处理器上都会被屏蔽。
共享的中断处理程序
共享处理程序与非共享处理程序有3点不同
1 request_irq()必须把flags设置成SA_SHIRQ。
2 dev_id 必须唯一。
3 中断处理程序必须能够区分他的硬件设备是否真的产生中断。(软件硬件都要支持)
中断上下文
进程上下文是一种内核所处的操作模式,此时内核代表进程执行。中断处理程序打断了其他代码,所以必须尽可能的迅速,简洁。为了减轻对内存的压力,因为系统中每个进程原先都需要两页不可换出的内核内存,为了应对栈大小的减少,中断处理程序用有了自己的栈,每个处理器1个,大小为1页,这个就是中断栈。
中断处理机制的实现
中断处理机制的实现特别依赖于体系结构,在内核中,中断的旅程开始于预定义入口点,这类似于系统调用通过预定义的异常句柄进入内核。对于每条中断线,处理器都会跳到对应的一个唯一的位置。然后内核调用函数do_IRQ()。
unsigned int do_IRQ(struct pt_regs regs)
中断控制
禁止中断可以禁止内核抢占,然而,不管是禁止中断还是禁止内核抢占。获取这些锁的同时也伴随着禁止本地中断。锁提供保护机制,防止来自其他处理器的并发访问,而禁止中断提供保护机制,则是防止来自其他中断处理程序的并发访问。

local_irq_disable()  禁止本地中断传递
local_irq_enable()   激活本地中断传递
local_irq_save()     保存本地中断传递的当前状态,然后禁止本地中断传递。
local_irq_restore()  恢复本地中断传递到给定的状态。
disable_irq()        禁止给定中断线,并确保该函数返回之前在该中断线上没有处理程序在运行。
disable_irq_nosync() 禁止给定中断线
enable_irq()         激活给定中断线
irqs_disabled()      如果本地中断传递被禁止,则返回非0,否则返回0。
in_interrupt()       如果在中断上下文中,则返回非0,如果在进程上下文中,则返回0。
in_irq()             如果当前正在执行中断处理程序,则返回非0,否则,返回0。



阅读(1428) | 评论(0) | 转发(0) |
0

上一篇:下半部和推后执行的工作

下一篇:socketpair

给主人留下些什么吧!~~