Linux驱动退出函数中未调用free_irq释放中断会引发哪些问题?
未释放已注册中断导致系统卡死的根本原因分析
1. 核心问题本质:内核全局资源残留野指针
- 调用
request_irq(共享中断场景常用request_threaded_irq)注册中断处理函数时,内核会将你传入的处理函数指针、dev_id参数等信息,添加到对应IRQ号的全局irqaction结构体链表中。该链表是内核的全局持久化资源,生命周期和系统运行周期一致,完全不受驱动模块加载/卸载的生命周期控制。 - 执行
rmmod卸载驱动时,内核仅会回收驱动模块自身占据的所有内存空间:包括中断处理函数所在的代码段、驱动私有数据所在的数据段/堆内存都会被标记为未使用,后续可能被其他内核任务分配复用。但该IRQ的irqaction链表中,仍然保留着指向这段已被释放内存的函数指针、数据指针,本质就是内核态的野指针。
2. 不同IRQ号的卡死时机差异原因
- IRQ 1是x86架构下PS/2键盘的默认硬件中断号,触发频率极高:只要有按键按下/抬起就会触发中断,部分设备的键盘还会定期发送状态中断。中断触发后内核会遍历该IRQ对应的
irqaction链表,依次调用所有注册的处理函数,一旦调用到已经释放的野指针地址,就会立刻触发内核态非法内存访问,直接导致系统崩溃或卡死,所以卸载驱动后故障立刻触发。 - IRQ 6默认对应软盘控制器中断,现代设备几乎都没有配备软盘硬件,该中断平时几乎不会被触发,因此野指针不会被立刻调用:
- 执行
cat /proc/interrupts时,内核会遍历所有IRQ的irqaction链表,统计中断触发次数、拉取处理函数的标识信息,遍历到你遗留的野指针条目时就会触发非法访问; - 再次执行
insmod注册同一个IRQ号的中断时,内核需要修改该IRQ的irqaction链表,访问到无效条目时也会触发异常。
- 执行
3. 共享中断的特殊影响
你注册的是共享中断,内核要求该IRQ触发后必须遍历完所有注册的irqaction条目,直到所有处理函数都执行完成才会结束中断上下文,因此只要链表中存在野指针,就一定会被访问到,不会因为同IRQ下有其他正常驱动的处理函数就规避故障。
内容的提问来源于stack exchange,提问作者agenius5
相关产品推荐
相关产品推荐

