Linux中断处理_第1页
Linux中断处理_第2页
Linux中断处理_第3页
Linux中断处理_第4页
Linux中断处理_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux中断处理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是向系统登记的中断处理函数, 是一个回调函数, 中断发生时, 系统调用这个

2、函数, dev_id参数将被传递;irqflags是中断处理的属性, 若设置SA_INTERRUPT, 表明中断处理程序是快速处理程序, 快速处理程序被调用时屏蔽所有中断, 慢速处理程序不屏蔽; 若设置SA_SHIRQ, 则多个设备共享中断, dev_id在中断共享时会用到, 一般设置为这个设备的device结构本身或者NULL.free_irq()的原型为:void free_irq(unsigned int irq, void *dev_id);另外, 与Linux中断息息相关的一个重要概念是Linux中断分为两个半部, 上半部(top half)和下半部(bottom half). 上半

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

4、断?1) 外设的处理速度一般慢于CPU2) CPU不能一直等待外部事件所以设备必须有一种方法来通知CPU它的工作进度, 这种方法就是中断.2. 中断实现在Linux驱动程序中, 为设备实现一个中断包含两个步骤:1) 向内核注册中断2) 实现中断处理函数3. 中断注册request_irq用于实现中断的注册功能:int request_irq(unsigned int irq, void (*handler)(int, void*, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);返回0表示成功

5、, 或者返回一个错误码.中断注册(参数)1) unsigned int irq 中断号2) void (*handler)(int, void *, struct pt_regs *) 中断处理函数3) unsigned long flags 与中断管理有关的各种选项4) const char * devname 设备名5) void *dev_id 共享中断时使用a) 中断注册(中断标志)在flags参数中, 可以选择一些与中断管理有关的选项, 如:1) IRQF_DISABLED(SA_INTERRUPT)如果设置该位, 表示是一个“快速”中断处理程序; 如果没有设置该位, 那么是一个“慢

6、速”中断处理程序.2) IRQF_SHARED(SA_SHIRQ)该位表明中断可以在设备间共享.b) 快速/慢速中断这两种类型的中断处理程序的主要区别在于: 快速中断保证中断处理的原子性(不被打断), 而慢速中断则不保证. 换句话说, 也就是“开启中断”标志位(处理器IF)在运行快速中断处理程序时是关闭的, 因此在服务该中断时, 不会被其他类型的中断打断;而调用慢速中断处理时, 其它类型的中断仍可以得到服务.c) 共享中断共享中断就是将不同的设备挂到同一个中断信号线上. Linux对共享的支持主要是为PCI设备服务. 共享中断也是通过request_irq函数来注册的, 但有三个特别之处:1)

7、 申请共享中断时, 必须在flags参数中指定IRQF_SHARED位2) dev_id参数必须是唯一的3) 共享中断的处理程序中, 不能使用disable_irq(unsigned int irq), 为什么? 如果使用了这个函数, 共享中断信号线的其它设备将同样无法使用中断, 也就无法正常工作了.4. 中断处理程序什么是中断处理程序, 有何特别之处? 中断处理程序就是普通的C代码, 特别之处在于中断处理程序是在中断上下文中运行的, 它的行为受到某些限制:1) 不能向用户空间发送或接收数据2) 不能使用可能引起阻塞的函数3) 不能使用可能引起调度的函数5. 中断处理函数流程void shor

8、t_sh_interrupt(int irq, void *dev_id, struct pt_regs *regs)/* 判断是否是本设备产生了中断(为什么要做这样的检测?) */value = inb(short_base);if(!(value & 0x80) return; /* 清除中断位(如果设备支持自动清除, 则不需要这步) */outb(value & 0x7F, short_base); /* 中断处理, 通常是数据接收 */. . . . . . /* 唤醒等待数据的进程 */ake_up_interruptible(&short_queue);6.

9、 释放中断当设备不再需要使用中断时(通常在驱动卸载时), 应当把IRQ返还给系统, 使用void free_irq(unsigned int irq, void *dev_id);中断处理下半部(推后处理的部分)Linux中断处理下半部有三种实现方式: 软中断, tasklet, 工作队列.1. 最简单的中断机制最简单的中断机制就是像芯片手册上讲的那样, 在中断向量表中填入跳转到对应处理函数的指令, 然后在处理函数中实现需要的功能. 类似下图:这种方式在原来的单片机课程中常常讲到, 一些简单的单片机系统也是这样用, 它的好处很明显, 简单, 直接.2. 下半部中断处理函数所做的第一件事情是什么

10、? 答案是屏蔽中断(或者是什么都不做, 因为通常如果不清除IF位, 就等于屏蔽中断了), 当然只屏蔽同一种中断. 之所以要屏蔽中断, 是因为新的中断会再次调用中断处理函数, 导致原来中断处理现场的破坏, 即破坏了interrupt context.随着系统的不断复杂, 中断处理函数要做的事情也越来越多, 多到来不及接收新的中断了. 于是发生了中断丢失, 这显然不行, 于是产生了新的机制: 分离中断接收与中断处理过程. 中断接收在屏蔽中断的情况下完成; 中断处理在使能中断的情况下完成, 这部分被称为中断下半部.从上图中看, 只看int0的处理, func0为中断接收函数, 中断只能简单地触发fu

11、nc0, func0则能做更多的事情, 它与funcA之间可以使用队列等缓存机制. 当又有中断发生时, func0被触发, 然后发送一个中断请求到缓存队列, 让funcA去处理. 由于func0做的事情是很简单的, 所以不会影响int0的再次接收. 而且在func0返回时就会使能int0, 因此funcA执行时间再长也不会影响int0的接收.3. 软中断下面看看linux中断处理, 作为一个操作系统显然不能任由每个中断都各自为政, 统一管理是必须的.Linux把不可中断部分的共同部分放在函数do_IRQ中, 需要添加中断处理函数时, 通过request_irq实现. 下半部放在do_softi

12、rq中, 也就是软中断, 通过open_softirq添加对应的处理函数.4. tasklet旧事物跟不上历史的发展时, 总会有新事物出现. 随着中断数的不断增加, 软中断不够用了, 于是下半部做了改进. 软中断使用轮询的方式处理, 假如正好是最后一种中断, 则必须循环完所有的中断类型才能最终执行对应的处理函数. 当年开发人员为了保证轮询的效率, 限制中断个数为32个.为了提高中断处理数量, 顺便改进处理效率, 于是产生了tasklet机制. tasklet采用无差别的队列机制, 有中断时才执行, 免去了循环查表之苦. tasklet作为一种新机制, 显然可以承担更多的优点, 正好这时候SMP

13、越来越火了, 因此tasklet中加入了SMP机制, 保证同种中断只在一个cpu上执行. 在软中断时代, 显然没有这种考虑. 因此同一种中断可以在两个cpu上同时执行, 很可能造成冲突.总结一下tasklet的优点:1) 无类型数量限制2) 效率高, 无需循环查表3) 支持SMP机制5. 工作队列前面的机制不论如何折腾, 有一点是不会变的, 它们都在中断上下文中执行. 什么意思? 说明它们不可挂起. 而且由于是串行执行, 因此只要有一个处理时间较长, 则会导致其他中断响应的延迟. 为了完成这些不可能完成的任务, 于是出现了工作队列. 工作队列说白了就是一组内核线程, 作为中断守护线程来使用.

14、多个中断可以放在一个线程中, 也可以每个中断分配一个线程. 工作队列对线程作了封装, 使用起来更方便. 因为工作队列是线程, 所以可以使用所有可在线程中使用的方法.tasklet其实也不一定是在中断上下文中执行, 它也有可能在线程中执行.假如中断数量很多, 而且这些中断都是自启动型的(中断处理函数会导致新的中断产生), 则有可能cpu一直在这里执行中断处理函数, 会导致用户进程永远得不到调度时间. 为了避免这种情况, Linux在中断数量过多时, 会把多余的中断处理放到一个单独的线程中去做, 就是ksoftirqd线程. 这样既保证了中断不多时的响应速度, 又保证了中断过多时不会把用户进程饿死

15、.由于不能保证tasklet或软中断处理函数一定会在线程中执行, 所以不能使用进程才能用的一些方法, 如放弃调度、长延时等.软中断、tasklet、工作队列的区别与联系Linux中断分为两个部分: 上半部分(中断处理程序)和下半部分(推后处理程序). 上半部分需要立即执行, 并且有严格的时间限制, 这些工作是在所有中断被禁止的情况下完成的, 剩余部分工作推迟到下半部分. 下半部分的任务是执行与中断处理密切相关但中断处理程序本身不执行的工作, 在Linux2.6的内核中存在三种不同形式的下半部实现机制: 软中断, tasklet和工作队列.下面比较三种机制的区别与联系:软中断1. 软中断是在编译期间静态分配的2. 最多可以有32个软中断3. 软中断不会抢占另外一个软中断, 唯一可以抢占软中断的是中断处理程序4. 可以并发运行在多个CPU上(即使同一类型的也可以), 所以软中断必须设计为可重入的函数(允许多个CPU同时操作), 因此需要使用自旋锁来保护其数据结构

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论