17 驱动模块的符号导出(一个驱动模块调用另一个驱动模块)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ForFuture_/article/details/79406467

驱动模块的符号导出(一个驱动模块调用另一个驱动模块)


查看elf文件的信息 :

readelf xxx.ko -a

UND标识的函数在内核符号表里都是“T”,表示是全局函数,也就是说只有全局函数,内核才会帮我们把相应的函数地址转换好

驱动模块里默认情况下不管是函数还是全局变量都是作局部使用(相当于在函数或者变量名前加了“static”)
如果需要作为全局使用,需要使用导出符号“EXPORT_SYMBOL(函数名或者变量)”,来声明函数或者变量为全局使用,提供给其它驱动模块调用


实现一个内核里的全局函数“funca”,在其它驱动模块里调用(myfunc.c):

#include <linux/init.h>
#include <linux/module.h>

void funca(char *str)
{
    printk("In funca : %s\n", str);
}

EXPORT_SYMBOL(funca);//将funca发布为内核里的全局函数,在其它驱动模块里调用

MODULE_LICENSE("GPL");

调用funca函数的mytest模块(mytest.c):

#include <linux/module.h>
#include <linux/init.h>

extern void funca(char *str);//外部声明

void funcb(char *str)
{
    printk("In %s : %s\n", __func__, str);
}

static int __init test_init(void)
{
    printk("This is the init func\n");

    funca("the aaaaaa");//调用外部全局函数
    funcb("the bbbbbb");//调用自己的函数

    printk("init\n");

    return 0;
}

static void __exit test_exit(void)
{
    printk("exit\n");
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");

Makefile文件(生成两个.ko文件):

obj-m += mytest.o
obj-m += myfunc.o

#linux源码编译路劲
KSRC := /目录路径/orangepi_sdk/source/linux-3.4.112/

#指定架构
export ARCH := arm

#指定编译器(交叉编译器)
export CROSS_COMPILE := arm-linux-gnueabihf-

all : 
    make -C $(KSRC) modules M=`pwd`

.PHONY : clean
clean : 
    make -C $(KSRC) modules clean M=`pwd`

Makefile文件(只生成一个.ko文件):

#通过test.o(不能与包含的任何一个.o文件同名)来生成test.ko(只生成一个.ko)
obj-m += test.o

#指定test.o中包含mytest.o和myfunc.o
test-objs := mytest.o myfunc.o

#linux源码编译路劲
KSRC := /home/sunwin/Desktop/orangepi_sdk/source/linux-3.4.112/

#指定架构
export ARCH := arm

#指定编译器(交叉编译器)
export CROSS_COMPILE := arm-linux-gnueabihf-

all : 
    make -C $(KSRC) modules M=`pwd`

.PHONY : clean
clean : 
    make -C $(KSRC) modules clean M=`pwd`

用生成两个.ko的Makefile编译后,加载和卸载mytest驱动模块时都会调用到myfunc里的funca函数。
加载驱动模块的顺序,如果myfunc驱动模块不先加载,则mytest模块会加载不成功。

卸载myfunc模块驱动时要先卸载myfunc模块,要是先卸载myfunc模块,因为myfunc里的函数被mytest模块调用,会导致卸载不了。

insmod myfunc.ko
insmod mytest.ko

rmmod mytest
rmmod myfunc

用生成一个.ko的Makefile编译后,加载和卸载test驱动模块时会调用myfunc里的funca函数。

insmod test.ko
rmmod test

编译加载模块后,可以在内核符号表里查看到驱动模块里的函数:

cat /proc/kallsyms | grep 函数名

猜你喜欢

转载自blog.csdn.net/ForFuture_/article/details/79406467