You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从IDT表中打印IRQ处理函数的实际名称?

如何从IDT表地址获取实际中断处理函数名

你通过内核模块打印IDT表时,发现Handler Name显示的是irq_entries_start+0x10/0x660这类通用中断存根地址,而非实际的设备驱动处理函数(比如NVMe的nvme_irq)。这是因为Linux内核的中断处理采用分层设计,IDT直接指向的是通用中断入口存根,而非最终的设备handler。

核心原因

Linux内核x86架构中,中断向量首先会进入通用中断存根(irq_entries_start系列),这些存根负责上下文保存、调用中断分发逻辑(如handle_irq),最终通过struct irq_desc结构体找到绑定到该IRQ的实际设备处理函数。因此IDT表中直接存储的是存根地址,而非设备handler的地址。

解决步骤

要获取实际的中断处理函数名,需要将IRQ编号关联到内核的irq_desc结构体,从中提取绑定的irqaction链表:

  • 获取IRQ对应的irq_desc结构体
    使用内核函数irq_to_desc(unsigned int irq),传入IRQ编号即可得到对应的描述符结构体。

  • 遍历irqaction链表获取实际handler
    irq_desc中的action成员是一个链表,每个节点struct irqaction包含:

    • handler:实际中断处理函数的指针
    • name:处理函数的名称字符串
    • next:链表下一个节点
  • 打印实际handler信息
    遍历链表时,使用内核打印的%pF格式符可以直接将函数指针解析为符号名(需内核开启符号表支持),同时可以直接读取name字段。

代码示例片段

修改你的内核模块,在打印IDT信息的同时,添加以下逻辑获取实际handler:

#include <linux/interrupt.h>
#include <linux/spinlock.h>

// 假设你已经遍历到对应的irq_num
struct irq_desc *desc = irq_to_desc(irq_num);
if (desc) {
    struct irqaction *action;
    // 加锁保护irq_desc的并发访问
    raw_spin_lock_irq(&desc->lock);
    action = desc->action;
    while (action) {
        printk(KERN_INFO "IRQ %d: Actual Handler: %pF (Name: %s)\n",
               irq_num, action->handler, action->name);
        action = action->next;
    }
    raw_spin_unlock_irq(&desc->lock);
}

注意事项

  • 内核版本适配:不同内核版本中irq_desc的结构或辅助函数可能有差异,例如部分版本需使用irq_desc_get_irq_handler等函数,需根据目标内核版本调整。
  • 符号表依赖:%pF解析函数名需要内核开启CONFIG_KALLSYMS配置,若内核未开启,可能只能显示函数地址。
  • 并发安全:访问irq_desc时必须使用raw_spin_lock_irq/raw_spin_unlock_irq保证并发安全,避免竞态问题。

内容的提问来源于stack exchange,提问作者Hansen Idden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:43:39