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
相关产品推荐
相关产品推荐

