linux 的中断使用总结

本文详细介绍了Linux系统的中断处理机制,包括硬中断与软中断的区别、顶半部与底半部的概念,以及具体的实现方式如tasklet、工作队列、软中断(softirq)和threaded_irq等,并解释了中断共享的场景。


分为两部分:顶半部底半部


顶半部用于执行时间短和需要立刻响应的必要中断,而底半部则执行时间上相对长和响应上可以延缓的程序,以便提高并发性。


PIC(Programmable Interrupt Controller
 高级可编程中断控制器(APIC)


中断查看:
jaho@ARX-II:~$ cat /proc/interrupts 

中断序号   中断次数  可编程中断控制器  设备名称(request_irq的dev_name字段)
           CPU0       CPU1       
  0:    9089869   11999244   IO-APIC-edge      timer
  1:        899         45             IO-APIC-edge      i8042
  8:          0          1                IO-APIC-edge      rtc0
  9:       2963        525           IO-APIC-fasteoi   acpi
 12:       5875      11372        IO-APIC-edge      i8042
 16:      12970      25385       IO-APIC-fasteoi   uhci_hcd:usb6
 17:         10         12             IO-APIC-fasteoi   uhci_hcd:usb7
 18:          0          0               IO-APIC-fasteoi   uhci_hcd:usb8
 19:     217422     193605     IO-APIC-fasteoi   ehci_hcd:usb2
 20:          0          0               IO-APIC-fasteoi   uhci_hcd:usb3
 21:          0          0               IO-APIC-fasteoi   uhci_hcd:usb4
 22:          0          0               IO-APIC-fasteoi   uhci_hcd:usb5
 23:         95         25             IO-APIC-fasteoi   ehci_hcd:usb1
 40:          0          0               PCI-MSI-edge      PCIe PME, pciehp
 41:          0          0               PCI-MSI-edge      PCIe PME, pciehp
 42:          0          0               PCI-MSI-edge      PCIe PME, pciehp
 43:          8          9               PCI-MSI-edge      mei
 44:    1422333       5821      PCI-MSI-edge      ahci
 45:        683        126           PCI-MSI-edge      eth0

。。。。。。




硬中断

request_irq();

note:
中断号可以在应的Irqs.h中获得,platform设备的中断号可以从platform_resource 中获得

禁止和使能:



软中断(低半部,顶半部(硬中断)执行完时)


1.
tasklet (用软中断实现的)(参考:drivers\mxc\security\sahara2\Sah_interrupt_handler.c)
note执行于软中断上下文,属于原子上下文,不允许休眠

禁止和使能: loal_bh_disable()        local_bh_enable()

                                         tasklet 名称          软中断回调
DECLARE_TASKLET(BH_tasksah_Intr_Bottom_Half, (unsigned long)&reset_flag);

static void sah_Intr_Bottom_Half(unsigned long reset_flag)  

int sah_Intr_Init(wait_queue_head_t * wait_queue)   //硬中断申请  
{
...........
                                                                  中断回调
result = request_irq(SAHARA_IRQ, sah_Intr_Top_Half, 0, SAHARA_NAME, NULL);
...........
}

// 硬中断函数
static irqreturn_t sah_Intr_Top_Half(int irq, void *dev_id)
{
#if defined(DIAG_DRV_INTERRUPT) && defined(DIAG_DURING_INTERRUPT)
LOG_KDIAG("Top half of Sahara's interrupt handler called.");
#endif

interrupt_count++;
reset_flag = sah_Handle_Interrupt(sah_HW_Read_Status());

/* Schedule the Bottom Half of the Interrupt. */
tasklet_schedule(&BH_task);// 对应的中断函数在适当时候将被执行

/* To get rid of the unused parameter warnings. */
irq = 0;
dev_id = NULL;
return IRQ_RETVAL(1);
}



2.
工作队列(参考:drivers\usb\musb\Musb_core.c)
note执行于内核线程上下文
在linux2.6.36后出现cmwq自动维护工作队列的线程池
以提高并发性。之前是在work内核线程中执行。


//定义工作队列和关联函数

struct work_struct xxx_wq

void  xxx_do_work(struct work_struct *work);

//中断处理底半部
void xxx_do_work(struct work_struct *work)
{
............
}

// 中断处理顶半部
irqreturn_t  xxx_interrupt(int irq, void *dev_id)
{
    .....
    schedule_work(&xxx_wq);
    .....
    return IRQ_HANDLED;
}

// 设备驱动模块加载

int xxx_int(void)
{
     // 申请中断
    reuqest_irq(xxx_irq, xxx_interrupt, 0, "xxx", NULL);
    // 初始化队列
    INIT_WORK(&xxx_wqxxx_do_work);
    .................
}

 // 设备模块卸载


void xxx_exit(void)
{
    ........
    //释放中断
    free_irq(xxx_irq, xxx_interrupt);
    .........
}




3.
软中断(softirq)(一般不用。。。。)
note:执行与原子上下文,不能休眠
禁止和使能: loal_bh_disable()        local_bh_enable()


注册:open_softirq()
触发:raise_softirq()


4.

threaded_irq(参考:driver\rtc\Rtc-ab8500.c  & driver\hwmon\Lis3lv02d.c


request_threaded_irq(unsigned int irq, irq_handler_t handler,

              irq_handler_t thread_fn, unsigned long irqflags,

              const char *devname, void *dev_id)

devm_request_threaded_irq()


handler 对应的中断函数执行完后,如果返回值是IRQ_WAKE_THREAD内核会分配新的线程处理这个 thread_fn函数



中断共享


申请中断时添加标志:IRQF_SHARED

类似于共用一条中断线,当中断到来时需要在中断处理函数中做判断处理


------------------------------------------------------------------------------------






参考:linux设备驱动详解 &互联网

































































<think>嗯,用户问的是Linux中断使用需要注意什么。这个问题挺专业的,可能用户是开发人员或者系统管理员,需要处理内核级别的编程或者优化。首先,我得回忆一下Linux中断处理的基本机制。中断处理分为上半部和下半部,上半部要快速执行,不能阻塞,这点很重要,否则会导致系统响应变慢甚至崩溃。 接下来要考虑的是中断上下文的问题。在中断处理函数中,不能使用可能引起睡眠的函数,比如kmalloc,或者信号量。用户可能在实际编码中遇到这样的问题,比如不小心调用了不安全的函数,导致内核崩溃,这时候需要提醒他们注意函数的可用性。 然后是关于共享中断的处理。如果多个设备共享同一个中断线,必须检查是否是自己的设备触发的中断,否则可能误处理其他设备的中断,导致系统不稳定。用户可能在配置硬件时遇到共享中断的情况,需要确保他们的驱动能够正确识别和处理。 另外,中断的并发和重入问题。中断处理函数可能被多个CPU同时执行,或者在处理过程中被同一中断再次打断,所以必须保证代码是可重入的,避免使用静态变量等可能导致竞争的条件。用户可能在多核环境下遇到竞态问题,需要加锁或者使用原子操作来保护共享数据。 时间限制也是关键。中断处理时间过长会影响系统性能,所以需要将耗时操作放到下半部,比如tasklet、workqueue或者软中断。用户可能在优化系统响应时,需要拆分处理流程,确保上半部尽可能快。 资源释放和错误处理也不能忽视。如果申请了中断线,一定要在模块卸载或出错时释放,否则会导致资源泄漏。用户可能在编写模块时忘记释放资源,导致系统资源耗尽。 中断亲和性的设置对于多核系统性能优化很重要,用户可能希望将中断绑定到特定CPU,减少缓存失效,提高处理效率。这可能涉及到系统调优,需要指导他们如何正确设置。 最后,中断嵌套和优先级的问题,虽然Linux默认关闭中断嵌套,但在某些实时补丁中可能开启,这时候需要注意代码的可重入性。用户可能在实时系统中遇到这种情况,需要特别处理。 总结一下,回答时要分点说明,每个注意事项都要结合实际应用场景,帮助用户理解为什么需要注意这些点,以及如何避免常见错误。同时,确保使用正确的中文术语和LaTeX格式,结构清晰,便于用户逐步理解和应用。</think>在Linux系统中使用中断时,需特别注意以下几点核心问题: $$\text{中断处理 = 上半部(Top Half) + 下半部(Bottom Half)}$$ 1. **快速执行原则** - 中断上半部(硬中断)必须尽可能简短,禁止包含阻塞操作(如等待I/O、信号量等) - 典型耗时操作应转移到下半部(软中断、tasklet或workqueue) 2. **中断上下文限制** - 不可调用可能引起睡眠的函数(如`kmalloc(GFP_KERNEL)`) - 避免使用`printk`等非原子操作(建议用`pr_debug`+动态调试) 3. **共享中断处理** ```c if (request_irq(irq, handler, IRQF_SHARED, devname, dev_id)) // 必须设置IRQF_SHARED ``` - 需在handler中通过设备状态判断是否本设备产生中断 4. **并发与重入控制** - 中断处理可能被多个CPU同时执行 - 对共享数据必须使用`spin_lock_irqsave()`保护 5. **时间敏感性** $$\Delta t_{\text{处理}} < \text{系统容忍延迟}$$ - x86默认时钟中断频率$HZ=1000$(1ms周期) - 单次中断处理时间建议控制在$\mu s$级 6. **资源管理** - 必须配套实现`free_irq()` - 模块卸载时必须释放注册的中断 7. **中断亲和性** - 多核系统中可通过`/proc/irq/<IRQ>/smp_affinity`设置CPU绑定 - 使用`irq_set_affinity_hint()`优化缓存局部性 8. **错误处理** - 必须处理`request_irq`的返回值 - 对于PCI设备,需实现中断恢复机制 9. **中断嵌套预防** ```c local_irq_disable(); // 关闭本地中断 local_irq_enable(); // 启用本地中断 ``` - 默认禁止中断嵌套,需谨慎处理临界区 典型中断处理流程示例: 1. 硬件触发中断信号 2. CPU保存上下文并跳转到中断向量 3. 执行驱动注册的handler(上半部) 4. 触发tasklet/workqueue(下半部) 5. 恢复中断上下文 实际开发中建议结合`ftrace`进行中断延迟分析,使用`perf`监控中断频率。对于实时性要求高的场景,可考虑采用`PREEMPT_RT`补丁实现线程化中断
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值