内核函数间的调用有两种方法:
1)、把需要调用的函数编译进模块,与C语言的静态库类似。
2)、把需要调用的函数导出到符号表,方便模块使用,与C语言的动态库类似。
hello.c
#include
#include
#include "call.h"
static int __init hello_init(void)
{
printk("hello world\n");
call_fun();
return 0;
}
static void __exit hello_exit(void)
{
printk("bye\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZackLee");
MODULE_VERSION("1.0");
call.c
#include
void call_fun(void)
{
printk("I'm call function\n");
}
//如果是导出符号表的方法,则需要以下代码
EXPORT_SYMBOL(call_fun);
MODULE_LICENSE("GPL");
call.h
#ifndef __CALL_H__
#define __CALL_H__
void call_fun(void);
#endif
静态法:
Makefile
obj-m := test.o
test-objs :=hello.c call.c
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
动态法:
Makefile
obj-m := hello.o call.o
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
静态法直接make,生成test.ko,insmod即可
动态法稍微麻烦一点。make生成hello.ko和call.ko,其实也可以分开make,没有顺序的要求,先生成hello.ko或者call.ko都可以。
在没有加载时,cat /proc/kallsyms |grep call_fun,看不到任何东东。
加载hello.ko,insmod hello.ko,会报错:insmod: error inserting 'hello.ko': -1 Unknown symbol in module。有未识别的symbol,即call_fun。所以需要先加载call.ko,insmod call.ko,加载成功。
cat /proc/kallsyms |grep call_fun,打印出如下:
f7c81050 r __ksymtab_call_fun [call]
f7c81058 r __kstrtab_call_fun [call]
说明内核已经识别出call_fun.
lsmod |grep call
call 609 0
这时加载hello.ko会成功,insmod hello.ko
lsmod |grep call
call 609 1 hello
表示call模块中有函数被hello模块引用
先卸载call会失败,rmmod call,会报错:ERROR: Module call is in use by hello
应该先卸载hello,rmmod hello,卸载成功。
lsmod |grep call
call 609 0
然后卸载call,rmmod call,卸载成功。
cat /proc/kallsyms |grep call_fun 不会打印任何东东。
本文来源:中国IT实验室 作者:佚名