Linux设备驱动 之 中断处理程序
注册中断处理程序
中断处理程序是管理硬件驱动程序的组成部分;如果设备使用中断,那么相应的驱动程序就注册一个中断处理程序;
驱动程序通过request_irq()函数注册,并且激活给定的中断线,以处理中断;request_irq()函数可能会睡眠,因此,不能再中断上下文或者其他不行允许阻塞的代码中调用该函数,因为在该函数调用过程中会使用kmalloc()来分配内存,而函数kmalloc()是可以睡眠的;
int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
参数irq标识要分配的中断号,对某些设备,这个值是预先确定的;而对大多数其他设备来说,这个值要么尅通过探测获取,要么可以通过编程动态获取;
参数handler指向这个中断的实际中断处理程序,当操作系统接收到中断,该函数就会被调用;
typedef irqreturn_t (*irq_handler_t)(int, void *)
参数flag可以为0,也可能是下列一个或者多个标志位的掩码;
IRQF_DISABLED-该标志被设置后,意味着内核在处理中断处理程序本身期间,要禁止所有其他中断;如果不设置,中断处理程序可以与除本身以外的其他任何中断同时运行;多数中断处理程序不会设置该位;这种用法留给希望快速执行的轻量级中断;
IRQF_SAMPLE_RANDOM-设备产生的中断对内核熵池有贡献,内核熵池负责提供从各种随机事件导出真正的随机数;
IRQF_TIMER-该标志是特别为系统定时器中断处理而准备的;
IRQF_SHARED-该标志标明可以在多个中断处理程序之间共享中断线;在同一个给定线上注册的每个处理程序必须指定这个标记;否则,在每条线上只能有一个处理程序;
参数name是与中断相关的ascii表示;
参数dev用于共享中断线,当一个中断处理程序需要释放时,dev将提供唯一的标志信息,以便从共享中断线的多个中断处理程序中删除指定的那一个;如果无须共享中断线,那么该函数赋值为NULL即可;但是如果中断线是被共享的,那么就必须传递唯一信息;实践中往往会通过它传递驱动程序的设备结构;这指针是唯一的,而且有可能在中断处理程序内被使用到;
释放中断处理程序
卸载驱动程序时,需要注销相关的中断处理程序,并释放中断线,需要调用下面函数:
void *free_irq(unsigned int, void *)
如果指定的中断线不是共享的,那么该函数删除处理程序时还将禁止这条中断线,如果中断线是共享的,则仅删除dev所对应的处理程序,而这条中断线本身只有在删除了最后一个处理程序时才会被禁用;
编写中断处理程序
typedef irqreturn_t (*irq_handler_t)(int, void *)
第一个参irq就是这个处理程序要响应的中断号;
第二个参数dev是一个通用指针,它与中断处理程序注册时传递给request_irq()的参数dev必须一致;对于每个设备而言,设备结构是唯一的,而且也可能在中断处理程序中用到,因此,常常被看做是设备指针dev;
中断处理程序的返回值是一个irqreturn_t类型,对着着两个不同的返回值:IRQ_NONE和IRQ_HANDLED;当中断处理程序检测到一个中断,但是该中断对应的设备并不是在注册处理函数期间指定的产生源时,返回IRQ_NONE;当中断处理程序被正确调用时,且确实是它所对应的设备产生了中断时,返回IRQ_HANDLED;
中断处理程序是无须重入的;当一个给定的中断处理程序正在执行时,相应的中断线在所有处理器上都会被屏蔽掉,以防止在同一个中断线上接收另外一个新的中断;通常情况下,其他中断都是被打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断线总是被禁止的;
中断控制
Linux内核提供了一组接口用于操作机器上的中断状态;这些接口为我们提供了能够禁止当前处理器的中断信息,或者屏蔽掉整个机器的一条中断线的能力;
控制中断系统的原因归根结底还是需要提供同步;通过禁止中断,可以确保摸个中断处理程序不会抢占当前的代码;此外,禁止中断还可以禁止内核抢占;然而,不管是禁止中断还是禁止内核抢占,都没有提供任何保护机制来防止来自其他处理器的并发访问;Linux支持多处理器,因此,内核代码一般都需要获取某种锁,防止来自前提处理器对共享数据的并发访问;获取这些所得同时也伴随着禁止本地中断;锁提供保护机制,防止来自其他处理器的并发访问,而禁止中断提供保护机制,则是防止来自其他中断处理程序的并发访问;
禁止和激活当前处理器上的本地中断的方式如下:
local_irq_disable()
local_irq_enable()
如果在调用local_irq_disable()之前就已经禁止了中断,那么该例程会带来危险;同样相应的local_irq_enable()也存在风险,它们将无条件的激活中断,尽管这些中断可能在开始时是关闭的;
内核提供了一种机制把中断恢复到以前的状态而不是简单的禁止或者激活;
local_irq_save(flags)
local_irq_restore(flags)
flags参数必须定义为unsigned long类型,是以值传递的,改参数包含了具体体系结构的数据,也就是包含中断系统的状态;因为至少有一种体系结构把栈信息与值相结合,所以这两个函数的调用必须在同一个函数中;
某些情况下,不需要禁止整个处理器上的所有中断,只禁止整个系统中一条特定的中断线就足够了;这就是所谓的屏蔽掉一条中断线;Linux提供了四个接口:
void disable_irq(unsigned int irq)
void disable_irq_nosync(unsigned int irq)
void enable_irq(unsigned int irq)
void synchronize_irq(unsigned int irq)
前两个函数禁止中断控制器上的指定中断线,即禁止给定中断向系统中所有处理器的传递;另外,函数只有在当前正在执行的所有处理器程序完成后,disable_irq()才能返回;因此,调用者不仅要确保不再指定线上传递新的中断,同时还要确保所有已经开始执行的处理程序已全部退出;disable_irq_nosync则不会等待当前中断处理程序执行完毕;
synchronize_irq等待一个特定的中断处理程序退出;如果该吹了程序正在执行,那么该函数必须退出后才能返回;
这些函数的调用可以嵌套,但在一条指定的中断线上,对disable_irq或者disable_irq_nosync的每次调用,都要对应调用一次enable_irq,只有在对enable_irq完成最后一次调用之后,才能真正激活中断线;
所有者三个函数可以从中断或者进程上下文中调用,而且不会睡眠;
禁止多个中断处理程序共享的中断线是不合适的,禁止了中断线就禁止了这条线上所有设备的中断传递,所以新设备驱动程序趋向于不使用这些接口;
通常有必要了解中断系统的状态,如中断是禁止的还是激活的,或者当前是否处于中断上下文的执行状态中;
Linux中提供了两个宏用来检查内核当前的上下文:
in_interrupt()
in_irq()
in_interrupt最有用,如果内核处于任何类型的中断处理中,他返回非0,说明内核此刻正在执行中断处理程序,或者正在执行下半部的处理程序;
in_irq只有在内核确实正在执行中断处理程序时才返回非0;
通常情况下,需要检查自己是否处于进程上下文中,也就是说,希望确保自己不在中断上下文中,这种情况很常见,因为代码要做一些睡眠这样只能从进程上下文中做的事;如果in_inerrupt()返回0,则此刻内核处于进程上下文中;
Linux设备驱动 之 中断处理程序的更多相关文章
- 蜕变成蝶~Linux设备驱动之中断与定时器
“我叮咛你的 你说 不会遗忘 你告诉我的 我也全部珍藏 对于我们来说 记忆是飘不落的日子 永远不会发黄 相聚的时候 总是很短 期待的时候 总是很长 岁月的溪水边 捡拾起多少闪亮的诗行 如果你要想念我 ...
- linux设备驱动:中断的实现
一.什么是中断 中断分两种: 1)中断,又叫外部中断或异步中断,它的产生是由于外设向处理器发出中断请求.其中外部中断也有两种,这是由配置寄存器设定的:普通中断请求(IRQ)和快速中断请求(FIQ).一 ...
- Linux设备驱动之中断支持及中断分层
快速中断:在开启快速中断时,其他中断不会打断快速中断. 多个中断共享一个中断号. 中断行为受到限制: 1.不能使用可能引起阻塞的函数 2.不能使用可能引起调度的函数 中断注册:request_irq( ...
- linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet x ...
- linux设备驱动归纳总结(六):2.分享中断号【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-90837.html xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- 【Linux开发】linux设备驱动归纳总结(六):2.分享中断号
linux设备驱动归纳总结(六):2.分享中断号 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- linux设备驱动归纳总结(六):1.中断的实现【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-90740.html linux设备驱动归纳总结(六):1.中断的实现 xxxxxxxxxxxxxxxx ...
- linux设备驱动归纳总结(六):1.中断的实现
linux设备驱动归纳总结(六):1.中断的实现 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——工作队列
linux设备驱动归纳总结(六):3.中断的上半部和下半部--工作队列 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
随机推荐
- spring将service添加事务管理,在applicationContext.xml文件中的设置
在applicationContext.xml文件中的设置为: <beans> <bean id="sessionFactory" class="org ...
- css的导入与基础选择器
css是什么 css也是一门标记语言,主要用作修改控制html的样式 css书写的位置(导入) css是用来控制页面标签的样式,但是可以根据实际情况书写在不同的位置, 放在不同位置有不同的专业叫法,可 ...
- vue之双向绑定
Vue的一大核心是双向绑定,在2.0中采用数据劫持,用Object.defineProperty实现,但作者已声明在3.0中会采用proxy实现 Object.defineProperty是什么? ...
- mysql 创建用户,授权,查询用户等
MySQL创建用户与授权 一. 创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username:你将创建的用 ...
- 【OGG 故障处理】OGG-01031
故障原因 -------------------- 网络异常,导致DP进程异常中断 故障现象 -------------------- 源端DP 进程全部挂起,且启动失败 GGSCI 34> ...
- 《基于Scyther的秘钥建立协议设计》-------摘抄整理
本篇论文额主要创新点: 利用Scyther软件,通过对一个不安全的秘钥建立协议逐步添加并验证安全属性,最终建立一个安全的秘钥建立协议. 通过形式化分析软件设计秘钥建立协议课可以提高协议设计效率,减 ...
- NORDIC BLE MAC ADDR
一个ble设备,地址可以分成2大类 1.Public Device Address(公共设备地址) 公共设备地址 Public Device Address是48bits的数字,就和电脑mac地址 ...
- 15、TDM模型
论文:https://arxiv.org/pdf/1801.02294.pdf 解析: 学习基于树的推荐系统深度模型 Learning Tree-based DeepModel for Recomme ...
- delphi TAdoQuery组件的close方法可能导致”列名无效“错误
1,故障现象 一次程序运行,出现如下错误: 对应代码如下: 2,故障分析 Query_alert_2的语句在查询分析器中单独执行是正常的.排除语句出错. 如果注解掉Query_alert_1,则错误变 ...
- mac安装MySQLdb(mysql-python模块)
折腾了有一会,网上资料很多,但是在实际安装时就会发现有很多坑,如下实战操作可行.供参考. Command "python setup.py egg_info" failed wit ...