Linux设备驱动中,中断处理非常重要,尤其是在嵌入式系统中,无时无刻不在与中断打交道,因此,中断处理必须要牢牢掌握。

设备在产生某个事件时通知处理器的方法就是中断。中断就是一个信号,当硬件需要通知CPU你该处理我的数据或状态时,就会发出这个信号,而处理器如果发现驱动注册了该中断信号,就会保存现场,执行中断处理程序,然后再恢复现场。中断处理程序和其他代码是并行的,因此必须考虑竞态问题。

1.注册中断

内核维护了一个中断信号线的注册表,驱动模块在使用中断前要先请求一个中断通道(或者 IRQ中断请求),并在使用后释放它。

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id);

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

中断处理例程可在驱动初始化时或在设备第一次打开时安装。推荐在设备第一次打开、硬件被告知产生中断前时申请中断,因为可以共享有限的中断资源。这样调用 free_irq 的位置是设备最后一次被关闭、硬件被告知不用再中断处理器之后。但这种方式的缺点是必须为每个设备维护一个打开计数。

i386 和 x86_64 体系定义了一个函数来查询一个中断线是否可用:

int can_request_irq(unsigned int irq, unsigned long flags); /*当能够成功分配给定中断,则返回非零值。但注意,在 can_request_irq 和 request_irq 的调用之间给定中断可能被占用*/

快速中断和慢中断

在现代内核中,快速和慢速中断的区别已经消失,剩下的只有一个:快速中断(使用 SA_INTERRUPT )执行时禁止所有在当前处理器上的其他中断(其他处理器仍然可以响应中断)。除非你充足的理由在禁止其他中断情况下来运行中断处理例程,否则不应当使用SA_INTERRUPT。这个在嵌入式系统中或许用的比较多。

/proc/interrupts:记录了中断信息统计

/proc/stat:记录了系统活动的底层统计信息

2.自动检测 IRQ 号

驱动初始化时最迫切的问题之一是决定设备要使用的IRQ 线,驱动需要信息来正确安装处理例程。自动检测中断号对驱动的可用性来说是一个基本需求。有时自动探测依赖一些设备具有的默认特性,以下是典型的并口中断探测程序:

if (short_irq < 0) /* 依靠使并口的端口号,确定中断*/

switch(short_base) {

case 0x378: short_irq = 7; break;

case 0x278: short_irq = 2; break;

case 0x3bc: short_irq = 5; break;

}

有 2 种方法来进行探测中断: 调用内核定义的辅助函数和DIY探测。

(1)调用内核定义的辅助函数

unsigned long probe_irq_on(void); /*这个函数返回一个未分配中断的位掩码。驱动必须保留返回的位掩码, 并在后面传递给 probe_irq_off。在调用probe_irq_on之后, 驱动应当安排它的设备产生至少一次中断*/

int probe_irq_off(unsigned long); /*在请求设备产生一个中断后, 驱动调用这个函数, 并将 probe_irq_on 返回的位掩码作为参数传递给probe_irq_off。probe_irq_off 返回在"probe_on"之后发生的中断号。如果没有中断发生, 返回 0 ;如果产生了多次中断,probe_irq_off 返回一个负值*/

(2)DIY探测

DIY探测与前面原理相同: 使能所有未使用的中断, 接着等待并观察发生什么。

3.实现中断处理例程

中断处理例程唯一的特别之处在中断时运行,它能做的事情受到了一些限制:

(1)中断处理例程不能与用户空间传递数据, 因为它不在进程上下文执行;

(2)中断处理例程也不能做任何可能休眠的事情, 例如调用 wait_event, 使用除 GFP_ATOMIC 之外任何东西来分配内存, 或者锁住一个信号量;

(3)处理者不能调用schedule()。

4.禁用中断

(1)禁用单个中断

void disable_irq(int irq);/*禁止给定的中断, 并等待当前的中断处理例程结束。如果调用 disable_irq 的线程持有任何中断处理例程需要的资源(例如自旋锁), 系统可能死锁*/

void disable_irq_nosync(int irq);/*禁止给定的中断后立刻返回(可能引入竞态)*/

void enable_irq(int irq);

(2)禁用全部中断

void local_irq_save(unsigned long flags);/*在保存当前中断状态到 flags 之后禁止中断*/

void local_irq_disable(void);/* 关闭中断而不保存状态*/

如果调用链中有多个函数可能需要禁止中断, 应使用 local_irq_save

void local_irq_restore(unsigned long flags); /*打开中断使用*/

void local_irq_enable(void);

在 2.6 内核, 没有方法全局禁用整个系统上的所有中断

5.中断顶半部和底半部

中断处理需要很快完成,可通过将中断处理分为两部分来解决这个问题:

(1)顶半部,立即执行,实际响应中断的例程(request_irq 注册的那个例程)

(2)底版本,被顶半部调度,并在稍后更安全的时间内执行的函数

Linux 内核有 2 个不同的机制可用来实现底半部处理:

(1)tasklet (首选机制),它非常快, 但是所有的 tasklet 代码必须是原子的。

(2)工作队列, 它可能有更高的延时,但允许休眠,执行在进程上下文中,但不允许与用户空间进行数据拷贝。

6.中断共享

Linux 内核支持在所有总线上中断共享,Linux大部分中断都是可以共享的。

在通过request_irq 安装处理例程时候,有些不同:

(1)当request_irq 时,flags 中必须指定SA_SHIRQ 位;

(2)dev_id 必须唯一。任何指向模块地址空间的指针都行,但 dev_id 绝不能设置为NULL。

请求一个共享的中断时,如果满足下列条件之一,则request_irq 成功:

(1)中断线空闲;

(2)所有已经注册该中断信号线的处理例程也标识了IRQ是共享。

一个共享的处理例程必须能够识别自己的中断,并且在自己的设备没有被中断时快速退出(返回 IRQ_NONE )。共享处理例程没有探测函数可用,但使用的中断信号线是空闲时标准的探测机制才有效。一个使用共享处理例程的驱动需要小心:不能使用 enable_irq 或 disable_irq,否则,对其他共享这条线的设备就无法正常工作了。即便短时间禁止中断,另一设备也可能产生延时而为设备和其用户带来问题,因为这个中断可能不是你一个驱动模块在关注。

7.中断驱动的 IO

当与驱动程序管理的硬件间的数据传送可能因为某种原因而延迟,驱动编写者应当实现缓存。

输入:当新数据到达时并且处理器准备好接受时,设备中断处理器。

输出:当设备准备好接受新数据或确认一个成功的数据传送时,设备产生中断。

linux下怎样看设备的中断号,Linux设备驱动的中断处理相关推荐

  1. imx6获取中断号_linux设备驱动归纳总结(六):2.分享中断号【转】

    linux设备驱动归纳总结(六):2.分享中断号 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  2. linux下必看的60个命令

    Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作.文件存取.目录操作.进程管理.文件权限设定等.所以,在Linux系统上工作离不开使用系统提供的命令.要想真正理解Linux系统, ...

  3. Linux下shell脚本之双色球摇号脚本

    Linux下shell脚本之双色球摇号脚本 一.脚本要求 二.脚本内容 三.运行脚本 一.脚本要求 二.脚本内容 三.运行脚本 一.脚本要求 1.编写脚本Lottery.sh,模拟摇号过程 2.6位数 ...

  4. linux 网卡强制千兆,linux下如何看网卡是千兆还是百兆的

    linux下如何看网卡是千兆还是百兆的方法如下:使用ethtool命令.ethtool是Linux下用于查询及设置网卡参数的命令.举例:[root@hvrhub~]#ethtooleth0Settin ...

  5. 如何实现Linux下的U盘(USB Mass Storage)驱动

    如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write LinuxUSB MSC (Mass Storage Class) Driver Crif ...

  6. linux格式化大于2t硬盘分区,linux下大于2tb硬盘格式化及挂载,linux下大于2t的分区方法,linux gpt分区表 管理 自动挂载分区...

    linux下大于2tb硬盘格式化及挂载,linux下大于2t的分区方法,linux gpt分区表 管理 自动挂载分区 (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找 ...

  7. 在linux下vcd光盘提取,linux下抓取Vcd的视频文件[Linux安全]

    赞助商链接 本文"linux下抓取Vcd的视频文件[Linux安全]"是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判 ...

  8. linux 下mysql忘记密码或者安装好linux后不知道mysql初始密码解决方案

    linux 下mysql忘记密码或者安装好linux后不知道mysql初始密码解决方案 参考文章: (1)linux 下mysql忘记密码或者安装好linux后不知道mysql初始密码解决方案 (2) ...

  9. linux中替换文件中的内容,linux下批量替换文件中的内容linux操作系统 -电脑资料...

    对于单个文件,使用sed命令很容易做到, grep命令可以查找单个文件或文件夹下文件中的内容,使用参数"r"或"-R"可以递归查找指定文件夹下的所有文件:参数& ...

最新文章

  1. 教你搞定补码不恢复余数除法中够减和商的关系
  2. 《深入理解Java函数式编程》系列文章
  3. c# string 转 datetime_tesseract || PDF转PNG转txt
  4. java urlconnection乱码_HttpURLConnection 请求乱码
  5. 基于Delphi7的木马程序的查杀设计与实现
  6. 2021五一杯数学建模B题 消防救援问题
  7. Web开发技术架构图
  8. 股市中如何用筹码分布选牛股,通达信幅图指标公式筹码寻牛
  9. 移动架构师第一站UML建模
  10. 字符间距加宽5磅怎么设置_如何设置将word文档的字符间距加宽
  11. (附源码)计算机毕业设计SSM建筑工程管理系统
  12. android 仿微信demo————微信发现界面实现
  13. 考研/嵌入式/我的所思所想及其他
  14. 用vfp实现断点续传
  15. 一键启动u盘的快捷键查询表
  16. 百度统计中的索引量和site:命令的百度收录量不一致的原因
  17. 【转】我的助理辞职了!—给不听话的下属看看
  18. 基于springboot高考填报志愿综合参考系统设计与实现-计算机毕业设计源码+LW文档
  19. java获取月末日期_Java -- 获取当前日期、当月月初日期、月末日期
  20. android 炫酷的自定义轮播图,Android实现炫酷轮播图效果

热门文章

  1. 软考网络管理员存储容量计算相关问题
  2. 如何在linux下启动和关闭oracle服务
  3. 学java交学费包分配_java 学生缴学费案例:
  4. java @valid 密码不一致_一个成熟的Java项目如何优雅地处理异常
  5. java变量小明扑克牌_算法练习篇之:扑克牌顺子
  6. Foxmail邮件字体大小怎么设置 Foxmail字体的设置方法
  7. win10 dns异常上不了网如何解决
  8. 台式机计算机怎么分割,编辑手把手教程 如何给电脑硬盘分区
  9. jar包在windows后台运行,通过.bat文件
  10. springboot前后端分离后权限原理浅谈