Linux内核模块间函数调用
在阅读本文之前,请阅读下linux kernel 模块化编程入门这篇文章。
模块的函数导出到符号表才可以供其他函数使用,需要用到宏:1
EXPORT_SYMBOL(sym)
该宏在include/linux/export.h里面。
既然模块间函数调用,我们要编写2个模块。
文件一:kernel_fun.h1
2
3
4
void fun(void);
文件二,要导出的模块文件:kernel_fun.c1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 以下4个宏分别是许可证,作者,模块描述,模块版本 */
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("yuuyuu");
MODULE_DESCRIPTION("kernel module hello");
MODULE_VERSION("1.0");
/* 入口函数 */
static int fun_init(void)
{
printk(KERN_ALERT "fun_init() start\n");
return 0;
}
void fun()
{
printk(KERN_ALERT "fun() is called\n");
}
/* 退出函数 */
static void fun_exit(void)
{
printk(KERN_ALERT "fun_exit() start\n");
}
/* 注册到内核 */
module_init(fun_init);
module_exit(fun_exit);
/* 导出符号表 */
EXPORT_SYMBOL(fun);
最后一行就是导出到符号表。
文件三,要调用模块文件二的函数:kernel_mod.c1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* 以下4个宏分别是许可证,作者,模块描述,模块版本 */
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("yuuyuu");
MODULE_DESCRIPTION("kernel module hello");
MODULE_VERSION("1.0");
/* 入口函数 */
static int mod_init(void)
{
printk(KERN_ALERT "mod_init() start\n");
/* 调用fun */
fun();
return 0;
}
/* 退出函数 */
static void mod_exit(void)
{
printk(KERN_ALERT "mod_exit() start\n");
}
/* 注册到内核 */
module_init(mod_init);
module_exit(mod_exit);
fun()
即是调用其他模块的函数。
这里要编译2个模块,对应的Makefile文件:1
2
3
4
5obj-m += kernel_mod.o kernel_fun.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
编译好这2个模块后,我们现在来验证。注意,因为kernel_mod依赖kernel_fun,所以我要先插入kernel_fun模块。
卸载模块的时候,我们要先卸载kernel_mod,原因同上。
依次插入kernel_fun,查看它的符号表,然后插入kernel_mod,查看dmesg:
可以看到kernel_fun的fun()被kernle_mod调用了。
延伸
How to export a struct between two kernel modules using EXPORT_SYMBOL or equivalent?
参考资料: