Linux中我们加载驱动时,经常使用insmod指令来加载驱动ko文件,不过有时加载时,会弹出一些错误提示,例如我想导入pppoe的ko文件,使用insmod pppoe.ko,报错如下
insmod: can't insert 'pppoe.ko': unknown symbol in module, or unknown parameter
这时一般是插入的ko文件,依赖的一部分函数,内核的符号集中不存在, 所以加载ko的时候报了异常。
此时可以采用使用 dmesg 查看内核的环形缓冲区中的报错信息,看看详细的错误提示。
dmesg | tail -n 20
错误提示如下:
...
[ 4599.864471] pppoe: Unknown symbol pppox_ioctl (err 0)
[ 4599.869983] pppoe: Unknown symbol ppp_input (err 0)
[ 4599.876623] pppoe: Unknown symbol unregister_pppox_proto (err 0)
[ 4599.883344] pppoe: Unknown symbol register_pppox_proto (err 0)
[ 4599.889546] pppoe: Unknown symbol pppox_unbind_sock (err 0)
[ 4599.896494] pppoe: Unknown symbol ppp_register_net_channel (err 0)
剩下的只要根据提示的错误函数,搜索一下看看属于那个ko就好,在导入这个ko之前导入依赖的ko文件。
下面是看到的别人的以篇分析记录一下:
----------------------------------------------------------------------------------------------------------------------------------------------------
问题分析思路:
例如要查看是否有var_set_integer这个内核符号,输入命令:
cat /proc/kallsyms | grep "var_set_integer"
如果内核中已经包含了这个符号,那么就会有相关的打印信息,否则不打印。
注:/proc/kallsyms会显示内核中所有的符号,但是这些符号不是都能被其他模块引用的(绝大多数都不能),能被导出的是符号的类型是大写的那些(例如T,U)。
使用modinfo确定模块依赖关系,再进一步确认符号调用,部分嵌入式系统中可能不包含该指令,此时请转移至搜索引擎。
[root@localhost sw_64-3_8]# modinfo linux-bcm-core.ko
filename: linux-bcm-core.ko
license: GPL //权限
description: BCM Core Device Driver
depends: linux-kernel-bde // 由此可看出linux-bcm-core.ko 依赖于linux-kernel-bde.ko
vermagic: 3.8.0-sw2f SMP mod_unload modversions //内核版本
在导入的ko源代码中,看是否有出错函数 使用EXPORT_SYMBOL,是否有extern声明
并且查看是否要做GPL声明:修改为 MODULE_LICENSE("GPL");
1. 如果你的模块需要输出符号给其他模块使用, 应当使用下面的宏定义:
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);//只用于包含 GPL 许可权的模块。
符号必须在模块文件的全局部分输出, 在任何函数之外, 因为宏定义扩展成一个特殊用途的并被期望是全局存取的变量的声明. 这个变量存储于模块的一个特殊的可执行部分( 一个 "ELF 段" ), 内核用这个部分在加载时找到模块输出的变量.
2. EXPORT_SYMBOL使用方法:
1)在模块函数定义之后使用EXPORT_SYMBOL(函数名);
2)在调用该函数的模块中使用extern对之声明;
3)首先加载定义该函数的模块,再加载调用该函数的模块。【模块加载顺序的前后要求,一般就是依赖于符号调用】
编译生成ko模块之后,用insmod命令加载此模块到内核。这个程序加载模块的代码段和数据段到内核。
接着, 连接模块中任何未解决的符号到内核的符号表上.
也就是说:
【insmod使用公共内核符号表来解析模块中未定义的符号】,公共内核符号表中包含了所有的全局内核项(即函数和变量)的地址,这是实现模块化驱动程序所必需的。
同时也可以【导出自身模块中的任何内核符号到公共内核符号表】,如图:
在通常情况下,模块只需实现自己的功能,而无需导出任何符号。但是,如果其他模块需要从某个模块中获得好处时,我们也可以导出符号。
Module.symvers contains a list of all exported symbols from a kernel build.
Module.symvers包含所有要导出的列表符号。
Module.symvers file 的语法格式:
0x2d036834 scsi_remove_host drivers/scsi/scsi_mod
当内核编译选项CONFIG_MODVERSIONS关闭时,所有的CRC值都为0x00000000。
http://lxr.free-electrons.com/source/Documentation/kbuild/modules.txt
http://blog.csdn.net/macrossdzh/article/details/4601648
http://secisland.blog.51cto.com/787880/319760