kernel_log之 version

本文详细介绍了Linux内核启动过程中如何打印版本和编译信息,并展示了相关代码片段。通过分析start_kernel函数及linux_banner定义,读者可以了解内核版本信息的构成和显示方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux kernel log 版本与编译信息

一般利用版本和编译信息用于确定每次修改内核代码后,了解本次运行是否是编译的kernel 镜像。

上面这个打印位于start_kernel 函数的下面代码中:

asmlinkage __visible void __init start_kernel(void)
{
    char *command_line;
    char *after_dashes;
 

   set_task_stack_end_magic(&init_task);
    smp_setup_processor_id();
    debug_objects_early_init();

    cgroup_init_early();

    local_irq_disable();
    early_boot_irqs_disabled = true;

    /*
     * Interrupts are still disabled. Do necessary setups, then
     * enable them.
     */
    boot_cpu_init();
    page_address_init();
    pr_notice("%s\n", linux_banner);
    setup_arch(&command_line);

上面红色部分打印出上面的log。

这里linux_banner定义如下:

/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
    "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
    LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

const char linux_proc_banner[] =
    "%s version %s"
    " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
    " (" LINUX_COMPILER ") %s\n";
 

需要注意,下面这个linux_proc_banner是在proc文件系统显示的version使用的。

static int version_proc_show(struct seq_file *m, void *v)
{
    seq_printf(m, linux_proc_banner,
        utsname()->sysname,
        utsname()->release,
        utsname()->version);
    return 0;
}

static int version_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, version_proc_show, NULL);
}

static const struct file_operations version_proc_fops = {
    .open        = version_proc_open,
    .read        = seq_read,
    .llseek        = seq_lseek,
    .release    = single_release,
};

static int __init proc_version_init(void)
{
    proc_create("version", 0, NULL, &version_proc_fops);
    return 0;
}
fs_initcall(proc_version_init);
 

 

<think>我们正在解决Bazel构建内核模块时的编译错误。错误信息是“error executing KernelModule command Exit 2”。这个错误通常发生在构建过程中,可能由多种原因引起,比如编译选项配置错误、依赖缺失、环境问题等。 由于Bazel用于构建内核模块相对较少见,我们需要逐步排查。以下步骤基于常规内核模块构建和Bazel使用经验: ### 1. **检查Bazel构建文件(BUILD)** 确保为内核模块正确配置了构建规则。例如,使用`kernel_module`规则时,需要指定内核源代码路径和正确的配置(如`.config`文件)。示例规则: ```python kernel_module( name = "mymodule", srcs = ["mymodule.c"], kernel = "//path/to/kernel:kernel", # 指向内核构建目标 ) ``` ### 2. **确认内核头文件可用** 构建内核模块需要内核头文件。如果使用预编译的内核头文件,请确保路径正确。如果从源代码构建,确保内核已配置并准备好模块构建。 ### 3. **检查Bazel输出日志** 运行Bazel时添加`--subcommands`选项,查看详细命令执行过程: ```bash bazel build --subcommands //your:target ``` 观察失败的具体命令(可能是`make`命令或脚本),并检查其输出错误。 ### 4. **环境变量和工具链** 确保构建环境包含必要的工具链(如gcc、make)。Bazel可能使用自定义工具链,检查是否包含内核构建所需工具。 ### 5. **内核配置** 内核模块构建需要正确的内核配置(如`CONFIG_MODULES=y`)。确保使用的内核配置正确。 ### 6. **权限问题** 如果构建过程中涉及文件创建,确保Bazel有足够的权限(特别是在沙盒环境中)。 ### 7. **依赖项** 如果模块依赖其他内核头文件或模块,确保这些依赖在Bazel中正确声明。 ### 示例调试步骤 假设错误日志显示`make`命令失败,我们可以尝试手动执行相同命令(从Bazel输出中复制)来调试。 #### 常见错误场景: - **缺少头文件**:检查内核头文件路径是否包含在编译器的`-I`选项中。 - **符号未定义**:可能缺少内核导出符号,检查模块代码是否正确使用`EXPORT_SYMBOL`。 - **编译器选项不兼容**:如使用过高版本的gcc编译旧内核,可能导致错误。 ### 参考引用 在构建内核模块时,原子上下文(atomic context)问题通常出现在运行时,而非编译时。但编译时错误Exit 2一般表示编译失败,需检查编译日志[^1]。另外,内核参数配置(如CPU隔离)通常不影响编译,但可能影响运行时行为[^2]。 §§相关问题§§ 1. 如何为Bazel配置自定义内核构建? 2. Bazel构建内核模块时如何指定交叉编译工具链? 3. 如何解决内核模块编译中的头文件缺失问题?</think>### 解决 Bazel 构建内核模块的编译错误(Exit 2) 当使用 Bazel 构建外部内核模块时遇到 `error executing KernelModule command Exit 2` 错误,通常由以下原因导致。请按顺序逐步排查: #### 1. **检查内核头文件依赖** - 确保系统已安装与当前内核**完全匹配**的头文件: ```bash # 查看当前内核版本 uname -r # 安装对应头文件(Ubuntu示例) sudo apt install linux-headers-$(uname -r) ``` - 验证头文件路径: Bazel 需要正确指向内核头文件目录(通常在 `/lib/modules/$(uname -r)/build`)。在 BUILD 文件中显式指定: ```python kernel_module( name = "your_module", srcs = ["module.c"], hdrs = ["header.h"], kernel = "/lib/modules/$(uname -r)/build", # 关键路径 ) ``` #### 2. **确认 Bazel 配置** - 在 WORKSPACE 文件中声明内核依赖: ```python local_repository( name = "kernel_build", path = "/lib/modules/$(uname -r)/build", # 路径需与实际一致 ) ``` - 检查内核模块规则是否正确定义(示例): ```python load("@bazel_tools//tools/build_defs/kernel:kernel.bzl", "kernel_module") kernel_module( name = "my_module", srcs = glob(["*.c"]), deps = [":module_headers"], kernel = "@kernel_build//:kernel", # 引用WORKSPACE定义 ) ``` #### 3. **排查权限问题** - Bazel 可能因沙盒权限无法访问内核文件: ```bash # 临时禁用沙盒测试 bazel build --spawn_strategy=local //your:target ``` - 若成功,需调整沙盒策略或添加权限规则。 #### 4. **检查编译器兼容性** - 确保内核模块使用与内核**相同版本的 GCC**: ```bash # 查看内核编译使用的GCC版本 cat /proc/version # 强制Bazel使用指定编译器 bazel build --cxxopt="-std=gnu11" --host_cxxopt="-std=gnu11" //your:target ``` #### 5. **分析详细构建日志** 获取完整错误信息: ```bash bazel build --subcommands --verbose_failures //your:target ``` 重点关注: - `make` 命令的失败输出(通常涉及缺失符号或头文件) - 文件路径解析错误(如绝对/相对路径混淆) #### 6. **验证模块源代码兼容性** - 确保模块代码不包含**用户空间API**(如 `libc` 函数) - 检查是否使用**原子上下文不兼容操作**(如休眠函数)[^1]: ```c // 错误示例:在原子上下文中调用休眠 static irqreturn_t handler(int irq, void *dev) { msleep(100); // 会触发 scheduling while atomic return IRQ_HANDLED; } ``` #### 7. **处理内核配置依赖** 若模块依赖特定内核选项(如 `CONFIG_X=y`): - 确保当前内核已启用该选项: ```bash grep CONFIG_X /boot/config-$(uname -r) ``` - 在 BUILD 文件中声明依赖: ```python kernel_module( ... config_settings = {"CONFIG_X": "y"}, # Bazel特定语法 ) ``` ### 常见解决方案总结 | 错误类型 | 解决措施 | |-------------------------|------------------------------------------| | 头文件缺失 | 安装匹配的 `linux-headers`,检查路径 | | 编译器版本不匹配 | 使用 `--copt` 指定兼容的GCC标志 | | 原子上下文违规操作 | 替换休眠函数为 `udelay()` 或重设计逻辑 [^1] | | 符号未导出 | 在内核中使用 `EXPORT_SYMBOL()` 导出符号 | | Bazel 沙盒权限问题 | 添加 `--spawn_strategy=local` 或调整沙盒规则 | > **重要提示**:若问题涉及原子上下文(如网卡驱动 `start_xmit`),需通过 `preempt_count()` 判断上下文类型,并在原子上下文中使用 `GFP_ATOMIC` 替代 `GFP_KERNEL` [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值