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

如何用ftrace追踪可加载内核模块的静态函数?以zram_init为例

追踪可加载内核模块中的静态函数

核心问题分析

你遇到的echo zram_init > set_graph_function失败,本质是静态函数未导出内核符号,导致ftrace无法通过函数名定位到它;模块未加载的问题只需先执行modprobe zram就能解决,这里重点讲静态函数的追踪方案。


方案1:修改模块源码导出符号(适合可重新编译场景)

如果能拿到模块源码并重新编译,这是最直接的方式:

  • 找到目标静态函数(比如zram_init或zram的writepage实现),去掉static修饰符,或者添加EXPORT_SYMBOL_GPL()宏导出符号:
    // 以zram_init为例
    int zram_init(...) {
        // 原函数逻辑
    }
    EXPORT_SYMBOL_GPL(zram_init);
    
  • 重新编译模块(make -C /lib/modules/$(uname -r)/build M=$(pwd) modules),加载新模块后,就能直接用ftrace的set_graph_function或set_ftrace_filter追踪该函数。

注意:静态函数设计为内部私有,导出仅适合调试场景,不要用于生产环境。


方案2:用kprobe动态追踪(无需修改源码,通用方案)

kprobe可以直接追踪内核任意地址,不受符号导出限制,步骤如下:

步骤1:获取静态函数的实际地址

  1. 先加载模块:modprobe zram
  2. 查看模块加载基址:
    cat /sys/module/zram/sections/.text
    # 输出类似:0xffffffffc0a20000
    
  3. 用nm查看模块文件中的静态函数偏移:
    nm zram.ko | grep zram_init
    # 输出类似:0000000000001234 t zram_init
    
  4. 计算实际地址:基址 + 偏移(比如0xffffffffc0a20000 + 0x1234 = 0xffffffffc0a21234)

步骤2:注册kprobe并开启追踪

  1. 注册探测点(替换为实际地址):
    echo 'p:my_zram_probe 0xffffffffc0a21234' > /sys/kernel/debug/kprobes/events
    
  2. 开启追踪:
    echo 1 > /sys/kernel/debug/tracing/tracing_on
    
  3. 查看trace输出:
    cat /sys/kernel/debug/tracing/trace
    

针对zram writepage的追踪

zram的writepage函数会注册到文件系统的address_space_operations中,你可以:

  • 先追踪通用的filemap_writepage函数,在trace中查看调用的具体函数地址,再将该地址对应到zram的静态writepage函数,用kprobe追踪;
  • 或者直接通过nm zram.ko找到zram writepage函数的偏移,计算实际地址后注册kprobe。

方案3:利用内核静态tracepoint(如果模块自带)

部分内核模块会内置调试用的静态tracepoint,查看是否有zram相关事件:

ls /sys/kernel/debug/tracing/events/zram/

如果存在zram_writepage等事件,直接启用即可:

echo 1 > /sys/kernel/debug/tracing/events/zram/zram_writepage/enable

这种方式无需关心函数是否静态,直接捕获业务逻辑事件。


追踪模块初始化函数(如zram_init)

如果要追踪未加载模块的初始化函数,可以结合模块加载事件+ kprobe:

  1. 先开启模块加载事件追踪:
    echo 1 > /sys/kernel/debug/tracing/events/module/module_load/enable
    
  2. 加载模块:modprobe zram,从trace中提取zram的加载基址;
  3. 用nm zram.ko得到zram_init的偏移,计算实际地址后注册kprobe;
  4. 重新加载模块(rmmod zram && modprobe zram),就能捕获初始化函数的调用。

必要的内核配置

确保内核开启了以下配置(可通过zcat /proc/config.gz | grep <CONFIG>验证):

  • CONFIG_KPROBES=y:启用kprobe
  • CONFIG_FTRACE=y:启用ftrace框架
  • CONFIG_KALLSYMS_ALL=y:显示所有符号(包括静态函数)
  • CONFIG_DEBUG_FS=y:挂载debugfs(默认已挂载到/sys/kernel/debug)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:35:13