- 🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)
- 🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd
- 🌐系列专栏:Linux技术
- 📰如觉得博主文章写的不错或对你有所帮助的话,还望大家三连支持一下呀!!! 👉关注✨、点赞👍、收藏📂、评论。
- 如需转载请参考转载须知!!
Linux内核模块中存在与内核同名的函数引发的问题
- 问题
- 问题分析
- 问题解决
- 问题小结
问题
- xxx_func.c和yyy_hw_ctl_api.c分别隶属于xxx和yyy两个不同的ko,xxx_func.c要通过函数名来调用yyy_hw_ctl_api.c中的函数,具体实现类似下面代码:
//xxx_func.h
typedef int (* HW_CTR_CALL)(int cmd);
//xxx_func.c
static HW_CTR_CALL xxx_hw_call = NULL;
char *yyy_hw_func_name = "yyy_hw_ioctl";void xxx_func()
{int cmd = 0;...yyy_hw_call = (HW_CTR_CALL) kallsyms_lookup_name(yyy_hw_func_name);if (yyy_hw_call){yyy_hw_call(cmd);}}
//yyy_hw_ctl_api.c
void yyy_hw_ioctl(int cmd)
{...
}
- 测试中发现,xxx.ko中对yyy_hw_call进行了调用,但实际功能没有生效。
问题分析
- 首先想到的是在yyy_hw_ioctl函数中增加打印,确认函数执行的逻辑及入参是否正确。但神奇的发现,yyy_hw_ioctl并没有被调用到。
- 接着,就想到查看符号表,结果发现,符号表中居然有两个同名函数,一个在内核中,一个在yyy.ko中:
root# cat /proc/kallsyms | grep yyy_hw_ioctl
c0008798 t yyy_hw_ioctl
bf113674 T yyy_hw_ioctl [yyy]
- 进一步,查看kallsyms_lookup_name的实现,发现它的逻辑是先在内核中查找符号,然后再在模块中查找。内核符号的优先级高于模块,于是,该调用进入了内核中的yyy_hw_ioctl函数,而非yyy.ko中的yyy_hw_ioctl函数。
/* Lookup the address for this symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name)
{char namebuf[KSYM_NAME_LEN];unsigned long i;unsigned int off;for (i = 0, off = 0; i < kallsyms_num_syms; i++) {off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));if (strcmp(namebuf, name) == 0)return kallsyms_sym_address(i);}return module_kallsyms_lookup_name(name);
}
EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
问题解决
- 找到原因之后,处理起来就简单了。可以重命名内核的函数或内核模块的函数。
问题小结
- 内核中的两个函数估计是不能重名的,但内核和模块之间的函数却是可以重名的。为了避免此类问题的发生,可在函数命名上下点功夫,如借鉴java包的思想,将A模块中的函数命名为A_module_xx_func.c。
如本文对你有些许帮助,欢迎大佬支持我一下,您的支持是我持续创作的不竭动力
支持我的方式