由request_irq()函数引发对中断的理解

本文深入讲解了Linux系统中中断的概念及处理流程,包括中断的基本原理、使用request_irq函数注册中断处理程序的方法及其参数含义,还介绍了中断处理程序的设计原则。

http://blog.chinaunix.net/uid-24666775-id-3787938.html

http://blog.chinaunix.net/uid-24666775-id-3787938.html


分类: LINUX

 

1、  中断的理解

中断你可以理解为就是一种电信号,是由硬件设备产生的然后发送给处理器,处理器接收到中断后,就会马上向操作系统反映此信号,之后就是系统的工作了。

这里有两个注意的地方,第一中断是随时都可以产生,意味着中断的处理程序随时都可以执行,所以得保证中断处理程序能够快速执行,才可能尽快的恢复中断代码执行,所以中断代码尽量简短。第二每一个中断都有自己唯一的数字标记,这样操作系统才能对症下药

2、  注册中断中断处理程序

中断处理程序是管理硬件的驱动程序的组成部分,每一设备都有相关的驱动程序,驱动程序可以通过request_irq()函数注册一个中断处理程序,并且激活给定的中断线,来处理指定的中断,原型如下:

int request_irq(unsigned int irq,

           irq_handler_t handler,

           unsigned long flags, const char *devname, void *dev_id)

第一个参数irq表示要分配的中断号,就我目前所接触的都是预先已经预定好的,还没试着通过探测或者动态来确定中断号

第二个参数handler是一个指针,指向处理这个中断的实际中断处理程序,只要操作系统一接收到中断,该函数就被调用,这个函数稍后讨论

第三个参数flags中断处理程序的标志,这个标志可以是一个也可以是多个,列举几个最重要的标志:

           IRQF_DISABLED: 该标志被设置后,意味内核在处理中断处理程序本身的时候,禁止了其他所有的中断。如果不设置,中断处理程序可 以与除本身之外的其他任何中断同时运行。显而易见我们一般不去这么野蛮的设置这个标志

           IRQF_TIMER:为系统定时器的中断处理而准备的

           IRQF_SHARED:这个中断标志经常能遇见,这个标志意思就是多个中断处理程序之间可以共享中断线,概括起来就是没有这个标志就只能独自一个人占用,标志了,就是很多人可以占用这个中断号来

第四个才参数就是自定义与中断设备相关的文本了

第五个参数dev,看到第三个参数中IRQF_SHARED时候,你会不会有这样的疑问,假如现在我要释放当前共享的指定这个中断程序时候,我如何释放?会不会把其他占用也会删除掉,这就是第五个参数的意义,如果中断线是共享的,那么就必须传递能够代表当前设备的唯一信息

request_irq()成功返回0,如果返回非0,就表示有错误发生,这个时候你可以考虑当前中断是否被占用了,所以可以加上IRQF_SHARED标志

3、  中断处理程序

这里延续上面的handler指针,原型如下:

           Static  irqreturn_t intr_handler(int irq, void *dev)

这里唠叨一下,不知道大家面试时候有没有遇到像这样的题目

__interrupt double compute_area (double radius)

{

double area = PI * radius * radius;

printf(" Area = %f", area);

return area;

},指出上面中断函数出现的错误,不知道的就认真看下面的  O(_)O

第一个参数irq就是这个处理程序要响应的中断号,这个我认为现在没有多大意义了,因为上面有讲述到第五个参数的意义

 第二个参数dev是一个通用的指针,同样的,还是将上面讲述到的第五个参数拿过来理解。

返回值irqreturn_t,先看下面的定义

enum irqreturn {

//中断处理程序检测到一个中断,但该中断对应的设备并不是在注册处理函数期间指定的产生源时,返回这个值

    IRQ_NONE,

//中断处理程序被正确调用且确实是它多对应的设备产生了中断,返回这个值

    IRQ_HANDLED,

    IRQ_WAKE_THREAD,

};

typedef enum irqreturn irqreturn_t;

关于描述到这里,我想对中断有一个大概的了解,说白了就是硬件向处理器发送一个电信号,系统收到信号之后根据初始化的标志去处理相应的中断处理程序。
如果熟悉中断的应该知道,我这里所有描述的其实都是中断处理程序的上半部,而下半部是什么,为啥要将中断分为上下部两部分?现在脑子里先有一个概念就是中断是随时产生的,也就意味着可能会打断了一些当前重要的工作而去处理你的中断处理程序,那当然我的中断程序是越快越好。同时中断他是不能被阻塞的,即不能在进程的上下文运行。基于上述原因 就是引入下半部的原因了。






<think> 首先,用户的问题是:挂载中断时应该选择使用request_irq还是devm_request_irq?我需要基于提供的引用内容来回答。 回顾引用内容: - [^1] 描述了devm_request_threaded_irq()函数的工作流程,包括如何注册中断顶半部和底半部,以及其自动释放资源的特点。 - [^2] 解释了中断标志如IRQF_TRIGGER_RISING等,并比较了request_irq和devm_request_irqrequest_irq需要手动释放,而devm_request_irq是自动管理的资源,不需要手动free_irq。 - [^3] 讨论了irq domain机制,但这不是直接相关的。 - [^4] 展示了使用request_irq和tasklet的中断处理模板,包括模块加载和卸载函数中的中断申请和释放。 用户的问题焦点是选择request_irq还是devm_request_irq。 关键点: - request_irq:需要手动调用free_irq来释放中断资源。 - devm_request_irq:自动管理资源,当设备移除时自动释放中断资源,减少了资源泄露的风险。 根据引用[^2],devm_request_irq的优势在于它是“managed”资源,避免了手动资源管理错误。 在回答时,我需要: - 使用中文。 - 结构化清晰:逐步解释,帮助用户理解。 - 确保真实可靠,基于引用。 - 生成相关问题。 - 在引用段落末尾添加引用标识,如[^1]。 回答结构: 1. 介绍两种函数。 2. 比较它们的区别。 3. 给出选择建议。 4. 解释理由,基于引用。 5. 生成相关问题。 最后,添加相关问题。 最终输出格式: - 用户可见层:回答清晰。 - 在末尾添加相关问题。 确保LaTeX语法正确:用户问题中没有数学表达式,所以可能不需要。 现在,草拟回答: - 开头解释两者。 - 区别:手动 vs 自动管理。 - 建议:优先使用devm_request_irq以简化代码和避免泄露。 - 引用来源:[^2]明确指出devm_request_irq自动回收资源。 - 示例:引用[^4]使用request_irq,但可以提到devm版本。 相关问题: 1. devm_request_irq是如何实现自动资源管理的? 2. 在共享中断时,request_irq和devm_request_irq有什么注意事项? 3. 如何使用devm_request_threaded_irq注册线程化中断? </think>### 挂载中断request_irq和devm_request_irq的选择 在Linux内核驱动开发中,挂载中断(即注册中断处理程序)是常见任务。`request_irq`和`devm_request_irq`都是用于申请中断资源的函数,但它们在资源管理方式上有显著区别。下面我将逐步解释两者的区别、选择建议和实际考量。 #### 1. **核心区别:资源管理机制** - **`request_irq`**: - 这是传统的中断申请函数。 - 需要**手动管理资源释放**:在驱动模块卸载或设备移除时,必须显式调用`free_irq`来释放中断资源。 - 使用场景:适用于资源管理需要精确控制的场景,例如在非设备模型驱动或复杂生命周期管理中。 - 示例:引用[^4]展示了在模块卸载函数中手动调用`free_irq`的模板: ```c /*设备驱动模块卸载函数*/ void __exit xxx_exit(void) { ...... /*释放中断*/ free_irq(xxx_irq, xxx_interrupt); // 必须手动释放 } ``` [^4] - **`devm_request_irq`**: - 这是“设备管理”(devres)版本的函数,基于Linux的设备资源管理框架。 - **自动管理资源释放**:当设备(`struct device`)被移除或驱动模块卸载时,内核自动调用释放函数,无需手动`free_irq`。这减少了资源泄露的风险。 - 使用场景:推荐在大多数设备驱动中使用,尤其是支持热插拔或资源管理简化的场景。 - 关键优势:如引用[^2]所述,`devm_request_irq`是申请的内核“managed”资源,自动回收资源: > devm_request_irqrequest_irq区别在于前者是申请的内核“managed”资源,不需要自己手动释放,会自动回收资源,而后者需要手动调用free_irq来释放中断资源 [^2]。 #### 2. **选择建议** - **优先选择`devm_request_irq`**: - 在大多数现代驱动开发中,`devm_request_irq`是更好的选择,因为它简化了代码并降低了资源泄露的可能性。尤其当驱动与设备模型(如`platform_device`)集成时,它能自动处理资源释放,提高代码可靠性。 - 例如,在热插拔设备或动态加载模块的场景中,自动管理能避免忘记释放中断导致的系统不稳定。 - **何时使用`request_irq`**: - 在以下情况下可能需要手动管理: - 驱动不依赖Linux设备模型(例如,某些旧式或自定义驱动)。 - 需要精细控制中断生命周期(例如,在运行时动态启用/禁用中断多次)。 - 共享中断(`IRQF_SHARED`标志)时,某些复杂场景可能需要手动介入 [^2]。 - **性能与兼容性**: - 两者在中断处理性能上无显著差异,因为核心处理逻辑相同。 - `devm_request_irq`内部调用`request_irq`,但添加了资源跟踪机制 [^1]。 #### 3. **实际使用注意事项** - **中断标志设置**:无论选择哪个函数,都需要正确设置中断标志(如`IRQF_TRIGGER_RISING`用于上升沿触发),这些标志定义在引用[^2]中 [^2]。 - **错误处理**: - `devm_request_irq`在错误时自动清理,而`request_irq`需在失败时手动回滚资源。 - 示例:使用`devm_request_irq`时,驱动模块卸载函数可以省略`free_irq`,代码更简洁。 - **线程化中断**:如果使用线程化中断(顶半部+底半部),`devm_request_threaded_irq`是更安全的自动管理版本 [^1]。 #### 总结 - **推荐`devm_request_irq`**:除非有特定需求(如精细资源控制),否则优先使用它以简化开发和维护。 - **理由**:自动资源管理减少了常见错误(如资源泄露),并符合现代Linux驱动的最佳实践。 如果您有具体代码上下文或驱动类型,我可以提供更针对性的建议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值