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

内核模块中tracepoints的使用方法及自定义irq跟踪事件咨询

跟踪内核中到达设备驱动前的IRQ事件

嘿,看你正在啃内核跟踪这块的硬骨头——kprobes、BPF/eBPF、tracepoints、perf这些工具都是内核调试和性能分析的利器,选对方向了!你想要跟踪到达设备驱动之前的IRQ事件,并且已经尝试在do_IRQ()里定义vector_irq_rcv这个tracepoint,这个思路非常准,毕竟do_IRQ()是内核处理硬中断的入口,确实是在设备驱动的中断 handler 之前执行的环节。

接下来我把你没写完的tracepoint代码补全,再一步步讲清楚怎么用:

先把你的tracepoint补全写规范

你贴的代码没写完,完整的vector_irq_rcv tracepoint应该是这样的:

TRACE_EVENT(vector_irq_rcv,
    TP_PROTO(unsigned int vector, unsigned int irq),
    TP_ARGS(vector, irq),
    TP_STRUCT__entry(
        __field( unsigned int, vector )
        __field( unsigned int, irq )
    ),
    TP_fast_assign(
        __entry->vector = vector;
        __entry->irq = irq;
    ),
    TP_printk("vector=%u, irq=%u", __entry->vector, __entry->irq)
);

简单解释下每个部分:

  • TP_PROTO:声明触发tracepoint时要传的参数类型
  • TP_ARGS:指定实际传递的参数名
  • TP_STRUCT__entry:定义要记录的事件数据结构,这里我们存了中断向量vector和对应的IRQ号irq——这俩是跟踪IRQ最核心的信息
  • TP_fast_assign:把参数值赋值给tracepoint的入口结构体,要高效
  • TP_printk:定义默认的打印格式,用trace-cmd或perf直接看的时候会用这个格式输出

把tracepoint挂到do_IRQ()里

找到内核源码里的do_IRQ()函数(不同架构位置不一样:x86在arch/x86/kernel/irq.c,通用路径可能是kernel/irq/irqdesc.c),在函数最开头(刚进入中断处理,还没调用驱动的中断处理函数之前)加触发代码:

void do_IRQ(struct pt_regs *regs)
{
    // 先拿到当前中断的vector和对应的irq号(x86架构示例)
    unsigned int vector = regs->orig_ax & 0xff;
    unsigned int irq = __this_cpu_read(vector_irq[vector]);

    // 触发我们的tracepoint,把数据打进去
    trace_vector_irq_rcv(vector, irq);

    // 下面是内核原本的IRQ处理逻辑,别碰
    struct irq_desc *desc = irq_to_desc(irq);
    // ... 后面的代码原样保留
}

注意:如果是ARM/ARM64架构,获取vector和irq的方式会不一样,得对应调整——比如ARM可能要从GIC寄存器里读,或者用架构提供的函数获取。


怎么验证和用这个tracepoint?

1. 编译内核要开对配置

确保内核config里打开了这些选项:

  • CONFIG_TRACEPOINTS=y(必须开,tracepoint的基础)
  • CONFIG_PERF_EVENTS=y(如果要用perf工具的话)
  • 有些架构还有CONFIG_IRQ_TRACEPOINTS=y,能开就开

2. 用trace-cmd实时看事件

# 启动trace,只跟踪我们的vector_irq_rcv事件
sudo trace-cmd record -e vector_irq_rcv
# 这时候去触发你的硬件中断(比如插个USB设备,或者跑个测试用例)
# 按Ctrl+C停止trace,然后看结果
sudo trace-cmd report

3. 用eBPF玩出花(更灵活)

既然你在学eBPF,用它来分析这个tracepoint的数据会更方便——比如过滤特定IRQ、统计频率啥的。给你整个BCC的脚本示例:

from bcc import BPF

# BPF程序代码
bpf_code = """
TRACEPOINT_PROBE(kernel, vector_irq_rcv) {
    // 从tracepoint里拿参数
    u32 vector = args->vector;
    u32 irq = args->irq;
    // 打印到trace管道
    bpf_trace_printk("Pre-driver IRQ: vector=%u, irq=%u\\n", vector, irq);
    return 0;
}
"""

# 加载BPF程序
b = BPF(text=bpf_code)
# 实时打印输出
print("Waiting for IRQ events...")
b.trace_print()

运行这个脚本,就能实时看到所有到达do_IRQ()的IRQ事件——这些都是还没到设备驱动处理的阶段,完全符合你的需求。


额外给你几个小技巧

  • 如果不想跟踪所有IRQ,可以在触发tracepoint的时候加个判断,比如只跟踪IRQ 44:if (irq == 44) trace_vector_irq_rcv(vector, irq);
  • 除了do_IRQ(),还可以盯handle_IRQ_event()——这是调用设备驱动中断handler的前一步,在这里加tracepoint也能精准抓驱动处理前的IRQ
  • 用perf也能直接看:sudo perf trace -e vector_irq_rcv,输出更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:15:25