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 ...
随机推荐
- flask 反向解析示例
1 静态网页 和动态网页 1 静态网页:无法与服务器做动态交互的网页 2 动态网页:允许与服务器做动态加护的 2 WEB 与 服务器 1 WEB :网页(HTML,css,JS) 3 服务器的作用: ...
- 跟着minium官网介绍学习minium-----(一)
某天,再打开微信开发者工具的时候收到一条推送.说是微信小程序自动化框架 Python 版 -- Minium 公测. Url如下: https://developers.weixin.qq.com/c ...
- Centos7下安装MongoDB4.0.10
前言 模式自由 :可以把不同结构的文档存储在同一个数据库里 面向集合的存储:适合存储 JSON风格文件的形式 完整的索引支持:对任何属性可索引 复制和高可用性:支持服务器之间的数据复制,支持主-从模式 ...
- Js获取字符串的显示宽度/高度
重点:1.在H5页面,文字大小单位为rem2.不同的font-family,文字的宽度不一样3.文字宽度同时受font-size和font-family影响 思路:在页面动态创建一个节点,设置节点的f ...
- #使用Python的turtle绘制正六边形、叠边形
1.#Python的turtle绘制正六边形 代码: len=100 #表示边长像素 import turtle as t #正六边形内角都是120度,外角60度 for i in range(6): ...
- P1006 传纸条[棋盘DP]
题目来源:洛谷 题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接 ...
- vue3.0脚手架 创建项目
1.下载node最新稳定版本,并且安装 2.安装好之后,在cmd或者terminal下, 使用npm -v 查看当前npm版本,验证是否安装成功 3.安装成功后,运行 npm i -g @vue/cl ...
- Spring MVC + freemarker实现半自动静态化
这里对freemarker的代码进行了修改,效果:1,请求.do的URL时直接生成对应的.htm文件,并将请求转发到该htm文件2,自由控制某个页面是否需要静态化原理:对org.springframe ...
- 基于Mint UI和MUI开发VUE项目一之环境搭建和首页的实现
一:简介 Mint UI 包含丰富的 CSS 和 JS 组件,能够满足日常的移动端开发需要.通过它,可以快速构建出风格统一的页面,提升开发效率.真正意义上的按需加载组件.可以只加载声明过的组件及其样式 ...
- Python中的基本类型简介
1.变量 变量不仅可以是数字,还可以是任意数据类型 命名规范:变量是用一个变量名表示,变量名必须是大小写英文.数字和下划线_的组合,且不能用数字开头 python中等号“=”是赋值语句,可以把任意数据 ...