EXPORT_SYMBOL在另一个linux设备驱动编译成ko文件的时候找不到
时间: 2023-12-06 12:03:39 浏览: 38
如果在另一个Linux设备驱动程序中使用了EXPORT_SYMBOL导出符号,但编译时找不到该符号,可能是以下原因导致的:
1. 缺少头文件:在使用EXPORT_SYMBOL导出符号的驱动程序中,可能缺少被导出符号的头文件。在另一个驱动程序中使用该符号时,也需要包含该头文件。因此,需要确保在使用被导出符号的驱动程序中包含了该头文件。
2. 编译顺序不正确:如果要使用一个驱动程序中导出的符号,需要在该驱动程序之前编译并加载。否则,当使用该符号的驱动程序被加载时,导出符号的驱动程序可能还没有被加载,从而找不到该符号。因此,需要确保导出符号的驱动程序先于使用该符号的驱动程序被编译并加载。
3. 符号命名冲突:如果多个驱动程序中使用了相同的符号名称,可能会导致符号命名冲突,从而导致编译错误。因此,需要确保在所有驱动程序中使用唯一的符号名称。
4. 编译参数不正确:在编译驱动程序时,需要正确设置编译参数,以便编译器能够找到导出符号的驱动程序。通常需要在Makefile文件中添加符号导出驱动程序的路径。
如果以上方法都无法解决问题,可以使用objdump命令查看编译后的KO文件中是否包含需要导出的符号。如果未找到该符号,说明导出驱动程序中的EXPORT_SYMBOL宏可能存在问题,需要检查导出驱动程序中符号导出的代码。
相关问题
EXPORT_SYMBOL 在编译ko的驱动中使用
在编译Linux内核模块时,EXPORT_SYMBOL用于将模块中定义的符号(函数、变量等)导出到内核空间,以便其他模块或内核代码可以使用这些符号。
以下是在编译ko驱动时使用EXPORT_SYMBOL的步骤:
1. 在驱动程序中定义需要导出的符号,例如:
```c
#include <linux/module.h>
#include <linux/kernel.h>
void my_function(void)
{
printk(KERN_INFO "My function called\n");
}
EXPORT_SYMBOL(my_function);
```
在上述例子中,my_function函数被定义并使用EXPORT_SYMBOL宏导出。
2. 编写Makefile文件以编译驱动程序,例如:
```
obj-m += my_driver.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
```
在上述例子中,Makefile文件使用obj-m变量定义要编译的模块名,并使用make命令编译模块。
3. 在终端中执行make命令编译驱动程序,例如:
```
$ make
```
4. 加载驱动程序,例如:
```
$ insmod my_driver.ko
```
在上述例子中,使用insmod命令加载my_driver.ko驱动程序。
5. 卸载驱动程序,例如:
```
$ rmmod my_driver
```
在上述例子中,使用rmmod命令卸载my_driver驱动程序。
需要注意的是,EXPORT_SYMBOL用于将符号导出到内核空间,因此只能在内核模块中使用。如果导出的符号是GPL协议的,应该使用EXPORT_SYMBOL_GPL宏。如果导出的符号是GPL或者可能在未来被GPL要求的,应该使用EXPORT_SYMBOL_GPL_FUTURE宏。
int my_var; EXPORT_SYMBOL_GPL(my_var);这样可以在其他驱动文件调用my_var了吗
使用 `EXPORT_SYMBOL_GPL` 导出的变量符号,可以在其他内核模块中使用。具体步骤如下:
1. 在某个 C 文件中定义变量,并使用 `EXPORT_SYMBOL_GPL` 宏定义导出该变量符号,例如:
```
// file1.c
int my_var = 0; // 定义变量 my_var
EXPORT_SYMBOL_GPL(my_var); // 导出变量 my_var
```
2. 为该 C 文件编译生成目标文件,例如:
```
gcc -c file1.c -o file1.o
```
3. 将生成的目标文件链接为一个库文件,例如:
```
ar rcs libmylib.a file1.o
```
4. 在其他驱动文件中使用该库文件,并使用 `extern` 关键字声明变量 `my_var`,例如:
```
// driver.c
#include <linux/module.h>
#include <linux/kernel.h>
#include "mylib.h" // 引用库头文件
extern int my_var; // 声明变量 my_var
int my_init(void)
{
printk(KERN_INFO "my_var = %d\n", my_var); // 输出变量 my_var 的值
return 0;
}
void my_exit(void)
{
printk(KERN_INFO "Goodbye\n");
}
module_init(my_init);
module_exit(my_exit);
```
```
// mylib.h
extern int my_var; // 声明变量 my_var
```
5. 为该驱动文件编译链接库文件,并生成内核模块,例如:
```
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
```
这里假设你的驱动代码位于当前目录下,使用 `make` 命令编译生成内核模块。
6. 加载该内核模块,并查看内核日志输出,例如:
```
insmod driver.ko
dmesg | tail
```
你应该可以看到类似如下的输出:
```
[ 7311.771679] my_var = 0
```
这样,变量 `my_var` 就可以在其他内核模块中共享了。需要注意的是,使用 `EXPORT_SYMBOL_GPL` 导出的符号只能在与内核相同的 GPL 许可证下使用。