Linux内核模块EXPORT_SYMBOL导出函数调用异常求助
问题分析与修复方案
核心问题总结
你的测试模块代码存在三个关键错误,导致fp_printk未正确执行且输出异常:
1. printk调用语法错误
KERN_INFO是内核日志级别宏,需要直接与格式字符串拼接,而非作为独立参数传递。错误写法会导致参数解析混乱,甚至丢失日志输出。
错误代码:
printk(KERN_INFO, "before exec\n");
正确写法:
printk(KERN_INFO "before exec\n");
2. 函数声明与调用遗漏
你仅声明了fp_printk的外部函数,但完全没有调用它!同时,extern声明的参数类型缺失,不符合内核代码的编译规范。
错误代码:
extern __visible void fp_printk(number, decimal_places, r);
正确声明+调用示例:
// 正确声明函数(需与原模块的函数签名完全匹配) extern __visible void fp_printk(int number, int decimal_places, char *destination); // 调用函数,传入具体数值和目标缓冲区 fp_printk(1234, 2, r); // 示例:将1234转换为保留2位小数的字符串"12.34"
3. 未初始化分配的内存
kmalloc分配的内存是未初始化的,可能包含随机垃圾数据。建议使用kzalloc(分配并清零)或手动memset初始化,避免输出乱码干扰调试。
优化后的内存分配:
// 使用kzalloc直接分配并清零内存 char *r = kzalloc(sizeof("12.34"), GFP_KERNEL); // 或者用kmalloc+memset // char *r = kmalloc(sizeof("12.34"), GFP_KERNEL); // if (r) memset(r, 0, sizeof("12.34"));
完整修复后的测试代码
printk(KERN_INFO "before exec\n"); // 分配并清零内存 char *r = kzalloc(sizeof("12.34"), GFP_KERNEL); if (!r) { // 增加内存分配失败的判断 printk(KERN_ERR "kmalloc failed\n"); return -ENOMEM; } // 正确声明并调用fp_printk extern __visible void fp_printk(int number, int decimal_places, char *destination); fp_printk(1234, 2, r); // 传入具体的数值和小数位数 printk(KERN_INFO "%s: %s\n", "test_fp_printk", r); printk(KERN_INFO "after exec\n"); // 记得模块退出时释放内存 kfree(r);
额外注意事项
- 确保
fp_printk的函数签名在原模块和测试模块中完全一致,包括返回值、参数类型和__visible属性。 - 内核模块间符号导出需确保原模块已正确加载(
insmod或modprobe),且测试模块编译时链接到内核符号表。
内容的提问来源于stack exchange,提问作者Guilherme Giácomo Simoes
相关产品推荐
相关产品推荐

