申请中断request_irq()与request_threaded_irq()之间的区别?

这篇博客主要对比了Linux内核中申请中断的两种方式:request_irq和request_threaded_irq。request_irq是一个wrapper,用于调用request_threaded_irq并将thread_fn设为空。request_threaded_irq在提供thread_fn时会创建一个处理线程irq_thread,用于处理不嵌套的中断。同时介绍了devm_request_irq和devm_request_threaded_irq作为设备管理器接口的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、申请中断函数原型

int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, 

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

======》

request_threaded_irq 两个完全相同的irq_handler_t类型的irq action : handler 和 thread_fn。


static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
   const char *name, void *dev)
{
return request_threaded_irq(irq,handler,NULL, flags, name, dev);
}

=====》

request_irq是request_threaded_irq的一个wrapper,只是将其中的thread_fn置为空。


二、request_threaded_irq函数实现

int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id)
{
struct irqaction *action;
struct irq_desc *desc;
desc = irq_to_desc(irq);

action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;

action->handler = handler;
action->thread_fn = thread_fn;
action->flags = irqflags;
action->name = devname;
action->dev_id = dev_id;
       .................
chip_bus_lock(desc);
retval =__setup_irq(irq, desc, action);
chip_bus_sync_unlock(desc);
       .................
return retval;
}


__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{
struct irqaction *old, **old_ptr;
unsigned long flags, thread_mask = 0;
int ret, nested, shared = 0;
cpumask_var_t mask;
       ......................................
/*
* Create a handler thread when a thread function is supplied
* and the interrupt does not nest into another interrupt
* thread.
*/
if (new->thread_fn && !nested) {
struct task_struct *t;

                // 为该irq创建一个线程:irq_thread  
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
  new->name);

if (IS_ERR(t)) {
ret = PTR_ERR(t);
goto out_mput;
}
/*
* We keep the reference to the task struct even if
* the thread dies to avoid that the interrupt code
* references an already freed task_struct.
*/
get_task_struct(t);
new->thread = t;

}


三、申请中断其它函数原型

devm_request_threaded_irq(struct device *dev, unsigned int irq,
 irq_handler_t handler, irq_handler_t thread_fn,
 unsigned long irqflags, const char *devname,
 void *dev_id);


static inline int __must_check
devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags,
devname, dev_id);
}


interrupt.h

manage.c

devres.c

<think>好的,用户想了解Android系统中devm_request_irq函数的用法及示例。首先,我需要回忆一下这个函数的作用。devm_request_irq是Linux内核中的资源管理函数,用于申请中断处理程序,并且具有自动释放资源的特性。Android系统基于Linux内核,所以这个函数在Android驱动开发中同样适用。 接下来,我应该整理这个函数的基本用法。根据引用[1]和[2],devm_request_irq的参数包括设备结构体指针、中断号、中断处理函数、标志位、设备名称和设备ID。同时,devm_free_irq用于释放中断,但通常不需要手动调用,因为使用了devm资源管理后,会在设备解除绑定或驱动卸载时自动释放。 然后,用户可能需要一个具体的示例代码。我需要构造一个简单的字符设备驱动示例,展示如何在probe函数中注册中断,并在中断处理函数中处理中断事件。需要注意的是,中断处理函数的返回类型是irqreturn_t,正确的返回值应该是IRQ_HANDLED或者IRQ_WAKE_THREAD,如引用[3]提到的。 另外,用户可能对错误处理和资源管理有疑问。需要强调devm系列函数在出错时会自动清理资源,但在实际开发中,还是需要检查返回值,处理可能的中断申请失败情况。例如,在示例代码中,检查返回值是否为非零,并在失败时打印错误信息。 用户还可能关心如何选择合适的标志位,比如IRQF_TRIGGER_RISING表示上升沿触发,或者IRQF_SHARED用于共享中断线。这里需要根据具体硬件的中断类型来设置,不同的触发方式会影响中断的触发条件。 最后,生成相关问题的时候,应该覆盖函数参数、错误处理、资源释放、标志位选择以及线程化中断处理等方面。这些问题可以帮助用户更深入地理解devm_request_irq的使用场景和注意事项,尤其是在Android驱动开发中的实际应用。</think>在Android/Linux内核驱动开发中,`devm_request_irq` 是用于申请中断处理函数的重要接口。其函数原型为: $$int \ devm\_request\_irq(struct\ device\ *dev, unsigned\ int\ irq, irq\_handler\_t\ handler, unsigned\ long\ irqflags, const\ char\ *devname, void\ *dev\_id)$$ ### 参数说明 1. `dev`: 关联的设备结构体指针 2. `irq`: 中断号,可通过`platform_get_irq()`获取 3. `handler`: 中断处理函数指针 4. `irqflags`: 中断标志,如`IRQF_TRIGGER_RISING` 5. `devname`: 设备名称标识 6. `dev_id`: 传递给处理函数的唯一标识 ### 示例代码(字符设备驱动) ```c static irqreturn_t sample_irq_handler(int irq, void *dev_id) { struct sample_data *data = dev_id; // 处理中断事件 return IRQ_HANDLED; // 返回类型参考引用[3] } static int sample_probe(struct platform_device *pdev) { struct sample_data *data; int irq = platform_get_irq(pdev, 0); // 申请中断 int ret = devm_request_irq(&pdev->dev, irq, sample_irq_handler, IRQF_TRIGGER_RISING, "sample_irq", data); if (ret) { dev_err(&pdev->dev, "无法注册中断 %d\n", irq); return ret; } return 0; } ``` ### 关键特性 1. 资源自动管理:当设备解除绑定或驱动卸载时自动释放中断(参考引用[2]) 2. 错误处理:返回非零值时表示注册失败 3. 线程化处理:可通过`IRQF_ONESHOT`标志实现中断线程化(参考引用[3])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值