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

如何配置Kbuild编译Linux内核模块的自定义section并生成__start_符号?

内核模块自定义section配置方案

在用户空间程序中,通过__attribute__((section("foo")))可以将变量放入自定义section,并通过__start_foo、__end_foo符号访问该section首尾,但该逻辑直接移植到内核模块时会触发Unknown symbol __start_foo错误——这是因为内核模块的Kbuild体系默认会丢弃未被显式引用的自定义section,且不会自动生成section首尾符号。

以下是解决该问题的具体配置和代码调整步骤:

1. Kbuild Makefile配置

在模块的Makefile中添加链接器参数,强制导出__start_foo和__end_foo符号,避免链接器丢弃相关section:

obj-m += simple_test.o
# 强制链接器保留foo section的首尾符号
KBUILD_LDFL_MODULE += -Wl,--undefined=__start_foo -Wl,--undefined=__end_foo

或者针对单个目标文件配置:

obj-m += simple_test.o
LDFLAGS_simple_test.o += -Wl,--undefined=__start_foo -Wl,--undefined=__end_foo

参数说明:--undefined=symbol告诉链接器将指定符号标记为未定义,强制链接器保留该符号对应的section,防止被优化丢弃。

2. 代码层面调整

(1)确保变量不被编译器优化

为自定义section的变量添加__attribute__((used))属性,防止编译器因变量未被直接引用而将其优化掉:

// 放入foo section的变量,添加used属性强制保留
static int var_on_foo __attribute__((section("foo"), used)) = 10;
static int var_on_foo2 __attribute__((section("foo"), used)) = 20;

(2)显式声明section首尾符号

在访问section的代码中,显式声明__start_foo和__end_foo的外部符号:

extern int __start_foo[];
extern int __end_foo[];

static void __init foo_section_test(void) {
    int *ptr;
    // 遍历foo section中的所有数据
    for (ptr = __start_foo; ptr < __end_foo; ptr++) {
        printk(KERN_INFO "foo section value: %d\n", *ptr);
    }
}

static void __exit foo_section_exit(void) {
    // 退出逻辑
}

module_init(foo_section_test);
module_exit(foo_section_exit);
MODULE_LICENSE("GPL");

原理说明

内核模块的编译链接流程与用户空间不同:

  • 编译器可能会优化掉未被直接引用的变量,used属性强制保留这些变量;
  • 链接器默认会丢弃未被显式引用的section,--undefined参数强制链接器保留section并导出首尾符号,确保内核模块加载时能识别这些符号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:52:55