Reprint Annotated Source: http://blog.csdn.net/xhz1234/article/details/44278137 Copyright Xu Hongzhi (Macrosan). All rights reserved.
A call relationship between modules is common, with two modules A, b,b using the function provided by the A module as an example, to explain the correct use of the method. Module A uses Export_symbol or EXPORT_SYMBOL_GPL to provide the function to be supplied to the B module, and Module B uses extern to declare the function provided by the A module.
The code is as follows:
Module A's Code –A_FUNC.C
#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/jiffies.h>//Print jiffiesvoidA_print_jiffies (void) {PRINTK ("Jiffies is:%llu\n", (U64) jiffies);return;} Export_symbol (a_print_jiffies);Static int__init A_init (void) {PRINTK ("A_func module init!\n");return 0;}Static void__exit A_exit (void) {PRINTK ("A_func module exit!\n");return;} Module_init (A_init); Module_exit (A_exit); Module_author ("[email protected]"); Module_description ("Module A"); Module_version ("0.1"); Module_license ("GPL");
Code for Module B –B_FUNC.C
#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/jiffies.h>extern voidA_print_jiffies (void);Static int__init B_init (void) {PRINTK ("B_func module init!\n"); A_print_jiffies ();return 0;}Static void__exit B_exit (void) {PRINTK ("B_func module exit!\n");return;} Module_init (B_init); Module_exit (B_exit); Module_author ("[email protected]"); Module_description ("Module b!"); Module_version ("0.1"); Module_license ("GPL");
Makefile of Module A
obj-m := A_func.oKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean: rm -f *.o *.ko *.mod.c *.order *.symvers
Makefile of Module B
obj-m := B_func.oKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean: rm -f *.o *.ko *.mod.c *.order *.symvers
Next, there are 3 ways to make module B compile and load without warning or failed.
method One:
A模块在make之后,会产生一个Module.symvers文件,将该文件拷贝到B模块源文件目录中,然后执行make
Method Two:
修改B模块的Makefile文件:添加KBUILD_EXTRA_SYMBOLS += /path_to_module_A/Module.symversexport KBUILD_EXTRA_SYMBOLS
obj-m := xhz2_func.oKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)KBUILD_EXTRA_SYMBOLS += /home/xhz/Project/Temp_Module/Module.symversexport KBUILD_EXTRA_SYMBOLSdefault: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean: rm -f *.o *.ko *.mod.c *.order *.symvers
Method Three:
修改Linux内核源码树中的Module.symers文件,将A模块编译产生的Module.symvers的内容添加在此文件中。(注意将空格替换为Tab,否则编译B时会报错)。
Personal recommendation Use the second method, which eliminates the steps to copy files compared to method one. There is no need to modify the module.symvers in the Linux kernel source tree compared to method three.
Reference
1.http://bbs.chinaunix.net/thread-1919530-1-1.html
2. "Deep Linux device driver kernel mechanism" – Chen Cossong Page45
The correct method for function call between Linux kernel modules