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 ...
随机推荐
- Django迁移
Django迁移 学习目标: 如何在不编写任何SQL语句的情况下创建数据库表 更改model如何自动修改数据库 如何还原对数据库所做的更改 迁移能解决的问题 如果你不了解Django或者WEB开发,肯 ...
- node express4 + 前端自动刷新
官网快速生成:http://www.expressjs.com.cn/starter/generator.html 1.安装 express 1.应用生成器工具 express-generator ...
- S2-032
前言 S2-032漏洞的影响范围是Struts 2.3.20 - Struts Struts 2.3.28,当开启了动态方法调用时可RCE.这次的漏洞分析以及后面的漏洞分析都是使用的Struts 2. ...
- 微服务、SOA、ESB比较
很多时候会听到微服务.SOA.ESB之间有着联系也有着区别,有时候了解了一下,过段时间有混肴模糊了今天看了一篇文章写的很好,特地记录一下. 原文地址:https://mp.weixin.qq.com/ ...
- 轻量级标记语言Asciidoc、Markdown
Asciidoc简介 https://blog.csdn.net/u011411849/article/details/79031718 Asciidoc 比Markdown更简洁强大的文档工具 ht ...
- Flutter——AspectRatio组件
AspectRatio 的作用是根据设置调整子元素 child 的宽高比. AspectRatio 首先会在布局限制条件允许的范围内尽可能的扩展,widget 的高度是由宽度和比率决定的,类似于 Bo ...
- 你应该使用Python3里的这些新特性
概述 由于Python2的官方维护期即将结束,越来越多的Python项目从Python2切换到了Python3.可是,在实际的工作中,我发现好多人都是在用Python2的思维去写Python3的代码, ...
- Spark(二)算子详解
目录 Spark(二)算子讲解 一.wordcountcount 二.编程模型 三.RDD数据集和算子的使用 Spark(二)算子讲解 @ 一.wordcountcount 基于上次的wordcoun ...
- C#readonly和const对比
readonly:常量,只能在声明时或构造函数中赋值,与static连用表示静态常量 const:静态常量,只能在声明时赋值
- 分享一波目前写的最强的autohotkey 插件
支持各种软件快速切换,补全括号,代码等!!!!!!!! ;这种全局定义要写在所有代码的前面才能让所有代码起作用. SetCapsLockState , AlwaysOff SetNumlockStat ...