当前位置: 首页 > 图文教程 > 操作系统 > Unix/Linux > 深入浅出 Linux设备驱动中断处理介绍

Unix/Linux
简析Linux中如何改变文件或目录的访问权限
初次安装Linux系统手记
Linux上搭建C/C++IDE开发环境
独辟蹊径:实现Linux下的局域网远程接入
不同发行版Linux操作系统如何实现共存
将Linux代码移植到Windows的简单方法
Linux系统中如何实现远程控制
linux系统如何访问NTFS磁盘
简单高效:用Swatch做Linux日志分析
全球顶尖超级计算机60%用Linux系统
Linux操作系统12则经典应用技巧
RedHat Linux操作系统配置技巧
Linux的防火墙配置—基础篇
浅谈Linux文件系统反删除方法
浅谈Linux优化及安全配置
解读Linux文件权限的设置方法
保护Linux下的Apache网站
如何在Linux下压缩文件
Linux爱好者入门教程
RedHat源码升级-(OpenSSL + OpenSSH)

Unix/Linux 中的 深入浅出 Linux设备驱动中断处理介绍


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-01   浏览: 148 ::
收藏到网摘: n/a

与Linux设备驱动中中断处理相关的首先是申请与释放IRQ的API: request_irq()和free_irq()。

request_irq()的原型为:

int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname, void *dev_id);

irq是要申请的硬件中断号;

handler是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递;

irqflags是中断处理的属性,若设置SA_INTERRUPT,标明中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置SA_SHIRQ,则多个设备共享中断,dev_id在中断共享时会用到,一般设置为这个设备的device结构本身或者NULL。

free_irq()的原型为:

void free_irq(unsigned int irq,void *dev_id);

另外,与Linux中断息息相关的一个重要概念是Linux中断分为两个半部:上半部(tophalf)和下半部(bottom half)。上半部的功能是"登记中断",当一个中断发生时,它进行相应地硬件读写后就把中断例程的下半部挂到该设备的下半部执行队列中去。因此,上半部执行的速度就会很快,可以服务更多的中断请求。但是,仅有"登记中断"是远远不够的,因为中断的事件可能很复杂。因此,Linux引入了一个下半部,来完成中断事件的绝大多数使命。下半部和上半部最大的不同是下半部是可中断的,而上半部是不可中断的,下半部几乎做了中断处理程序所有的事情,而且可以被新的中断打断!下半部则相对来说并不是非常紧急的,通常还是比较耗时的,因此由系统自行安排运行时机,不在中断服务上下文中执行。

Linux实现下半部的机制主要有tasklet和工作队列。

tasklet基于Linux softirq,其使用相当简单,我们只需要定义tasklet及其处理函数并将二者关联:

void my_tasklet_func(unsigned long); //定义一个处理函数:

DECLARE_TASKLET(my_tasklet,my_tasklet_func,data); //定义一个tasklet结构my_tasklet,与my_tasklet_func(data)函数相关联

然后,在需要调度tasklet的时候引用一个简单的API就能使系统在适当的时候进行调度运行:

tasklet_schedule(&my_tasklet);

此外,Linux还提供了另外一些其它的控制tasklet调度与运行的API:

DECLARE_TASKLET_DISABLED(name,function,data); //与DECLARE_TASKLET类似,但等待tasklet被使能 tasklet_enable(struct tasklet_struct *); //使能tasklet tasklet_disble(struct tasklet_struct *); //禁用tasklet tasklet_init(struct tasklet_struct *,void (*func)(unsigned long),unsigned long); //类似DECLARE_TASKLET() tasklet_kill(struct tasklet_struct *); // 清除指定tasklet的可调度位,即不允许调度该tasklet

我们先来看一个tasklet的运行实例,这个实例没有任何实际意义,仅仅为了演示。它的功能是:在globalvar被写入一次后,就调度一个tasklet,函数中输出"tasklet is executing":