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

Ubuntu下内核模块调用printk提示KERN_INFO未定义报错

报错原因
  • KERN_INFO是Linux内核定义的日志级别宏,对应宏定义存放在内核头文件<linux/kern_levels.h>中。5.10之前的旧版本内核中,该头文件会被<linux/kernel.h>自动引入,不需要手动包含;但Ubuntu 22.04及更新版本搭载的5.15、6.x系列内核,调整了头文件依赖关系,不会默认自动包含kern_levels.h,代码未显式引入对应头文件时,编译器就无法识别KERN_INFO宏,抛出未定义错误。
  • 若未使用内核模块标准构建流程,直接用gcc以用户态程序编译规则手动编译模块,会导致编译器无法定位内核头文件路径,也会触发该类宏未定义报错。
修复方案
  • 补全必要头文件
    在代码头部显式引入依赖头文件:
#include <linux/kernel.h>   // printk函数声明
#include <linux/kern_levels.h> // 包含KERN_INFO等日志级别宏定义

如果使用更简洁的封装接口,也可以直接引入<linux/printk.h>,使用pr_info替代printk+KERN_INFO的写法,该宏已经内置了INFO级别的日志标记,不需要手动拼接日志级别字符串:

#include <linux/printk.h>
// 直接调用即可,不需要传入KERN_INFO
pr_info("Hello world 1.\n");
pr_info("Goodbye world 1.\n");
  • 检查语法正确性
    确认KERN_INFO和后续日志格式字符串之间没有逗号。KERN_INFO本质是字符串常量宏,编译时会和后面的字符串自动拼接,加逗号会被识别为两个独立函数参数,触发语法或类型错误。给出的问题代码片段该部分语法是正确的,不需要调整。

  • 使用标准内核模块构建流程
    不要直接调用gcc命令手动编译模块,在代码目录下编写标准Makefile:

obj-m += hello_world.o
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

之后在目录下执行make命令即可完成编译,构建系统会自动关联当前运行内核的头文件路径、加载正确的内核编译配置,不会出现头文件找不到的问题。

修复后完整示例代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kern_levels.h>

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello world 1.\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye world 1.\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:27:22