可加载内核模块__init与__exit宏使用困惑及缓存失效疑问
关于可加载内核模块中__init和__exit宏的疑问
我清楚__init和__exit宏在内置内核模块中的作用,但在定义可加载模块的入口和出口函数时使用这些宏,我完全摸不着头绪,感觉这么做毫无意义。
我做了一个简单实验,编写了如下基础模块:
#include <linux/module.h> #include <linux/init.h> static int __init helloworld_init(void) { printk("\"Hello world initialization!\"\n"); return 0; } static int init_wrapper(void) { // 在这里调用初始化函数 return helloworld_init(); } static void __exit helloworld_exit(void) { printk("\"Hello world exit, let's try calling init here\"\n"); init_wrapper(); } module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("AjB"); MODULE_DESCRIPTION("LKM skeleton");
在/proc/kallsyms中搜索'helloworld',找不到__init函数的符号:
0000000000000000 r _note_7 [helloworld] 0000000000000000 t helloworld_exit [helloworld] 0000000000000000 d __this_module [helloworld] 0000000000000000 t cleanup_module [helloworld]
显然该函数已被移除,所以没出现在结果里。但我在__exit函数中调用了这个__init函数,卸载模块时的内核消息显示调用成功:
Mar 19 17:27:28 aijazVM kernel: [22750.453020] "Hello world exit, let's try calling init here" Mar 19 17:27:28 aijazVM kernel: [22750.453023] "Hello world initialization!"
这太奇怪了:__init函数的符号不存在,但同一文件内的函数居然还能调用它。我猜测可能是相关内存缓存行未失效,且同一编译单元内的函数引用是基于偏移的。但我尝试刷新缓存后,内核依然没有崩溃:
Mar 19 18:01:33 aijazVM kernel: [24795.884795] "Hello world initialization!" Mar 19 18:02:01 aijazVM kernel: [24823.169160] echo (15514): drop_caches: 3 Mar 19 18:02:12 aijazVM kernel: [24834.528229] "Hello world exit, let's try calling init here" Mar 19 18:02:12 aijazVM kernel: [24834.528232] "Hello world initialization!"
我有两个疑问:
- 为什么__init函数的符号不在kallsyms中,但同一编译单元内的__exit函数仍能成功调用它?
- 有没有方法强制CPU失效整个缓存层级?有没有架构无关的安全方式,让处理器失效本地缓存(L1/L2/L3)?
内容的提问来源于stack exchange,提问作者Skegg
相关产品推荐
相关产品推荐

