添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在调试过程中,发现一个问题,编译生成一个KO文件,insmod加载后报错:

Unknown symbol var_set_integer (err 0)

Unknown symbol parse_arg_eq (err 0)

问题分析思路:

一、用命令查看内核中是否已有这个内核符号

例如要查看是否有 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  //内核版本

三、在源码中搜索这几个函数定义的地方,看是否有使用 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,看是否存在要找的符号。

Module.symvers contains a list of all exported symbols from a kernel build.

Module.symvers 包含所有要导出的列表符号。

Module.symvers file 的语法格式:
<CRC>         <Symbol> <module>
0x2d036834    scsi_remove_host     drivers/scsi/scsi_mod

当内核编译选项CONFIG_MODVERSIONS关闭时,所有的CRC值都为0x00000000。

Linux模块间通讯方法非常的多,最便捷的方法莫过于函数符号导出,然后直接调用 。】

驱动也是存在于内核空间的,它的每一个函数每一个变量都会有对应的符号,这部分符号也可以称作内核符号,
它们不导出(EXPORT_SYMBOL)就只能为自身所用,导出后就可以成为公用 ,对于导出的那部分内核符号就是我们常说的内核符号表

insmod的时候并不是所有的函数都得到内核符号表去寻找对应的符号,
每一个驱动在自已的分配的空间里也会存在一份符号表,里面有关于这个驱动里使用到的变量以及函数的一些符号,首先驱动会在这里面找,如果发现找不到就会去公共内核符号表中搜索,搜索到了则该模块加载成功,搜索不到则该模块加载失败。

2.6内核默认情况下,是不会在模块加载后把模块中的 非静态全局变量 以及 非静态函数 自动导出到内核符号表中的,需要显式调用宏EXPORT_SYMBOL才能导出。
对于一个模块来讲,如果仅依靠自身就可以实现自已的功能,那么可以不需要要导出任何符号,只有其他模块中需要使用到该模块提供的函数时,就必须要进行导出操作。
由此启发,因为LKM中所存取的每一个符号(像函数名)也会被列在内核符号表中,有时候我们可以看内核符表就可以看到LKM调用的那些函数,如果这个LKM为非法目的,那么我们可以杀掉这个LKM.

名词解释:【 LKM: 可装载模块(Loadable Kernel Module )】

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

Linux 内核 的2.6某个版本开始, 内核 引入了导出 符号 的机制。只有在 内核 中使用EXPORT_ SYMBOL 或EXPORT_ SYMBOL _GPL导出的 符号 才能在 内核模块 中直接使用。然而, 内核 并没有导出所有的 符号 。例如,在3.8.0的 内核 中,do_page_fault没有被导出。   而我的 内核模块 中需要使用do_page_fault,那么有那些方法呢?这些方法分别有什么优劣呢?   下面以do_page_fault为例,一一进行 分析 :   1、修改 内核 ,添加EXPORT_ SYMBOL (do_page_fault)或EXPORT_ SYMBOL _GPL(do_page_fault)。 首先是 加载 内核模块 时报错: Nov 26 19:42:05 baijiaao kernel: hell ow orld: Unknown symbol __x86_indirect_thunk_rax (err 0) Nov 26 19:59:46 baijiaao kernel: hell ow orld: disagrees ...
记录一下,省的忘记。在跟着隔壁家教程学习写 LINUX 驱动框架的时候遇到的一些问题,已解决记录一下: 1.串口输出 Unknown symbol __class_create (err 0)这种系列提示 在网上查找资料发现是因为没有写这句代码:MODULE_ LI CENSE("GPL"); 之前移植没有注意这句代码,以为写完 module_init(xxx_init); module_exit(xxx_exit); 这两句代码就算结束了,谁知到还有这个坑。 2. Unknown symbol device_crea
问题这几天在arm上做蓝牙耳机驱动的时候,编译好了驱动但是在板子上insmod时候。 怎么会出现这种情况,不对呀,仔细查我们会发现,其实编译驱动的时候,就出现了一些警告,只是当时没有在意而已,而恰恰是这些警告导致的这些问题。 板子用的是realarm 内核 linux -2.6.35 交叉编译器arm- linux -gcc 4.4.3 问题解析究其原因,其原因就是我们
今天开始调试usb驱动,第一步 加载 模块 部分就开始报错。网上检索,有位朋友总结一些类似情况。本人遇到的恰好是第二种情况,以前不太注意,没出错也就不追究,这次遇到了就一并把一些情况在此记上一笔。转载如下: insmod: error inserting 'cmos_driver.ko' : -1 File exists 和 insmod: error inserting './cmos_driver
加载 驱动 模块 时报错: “ Unknown symbol CFG80211_SupBandReInit (err 0)” 查看了 内核 代码以及 加载 上的 symbol (命令为 cat /proc/kall sym s, 未找到对应值),依旧没有解决问题。 最后试探性查看编译时所需的Makefile,发现是因为条件编译导致未编ko文件所致,因此需要确认一下2点: (1)函数以及函数所在的文件是否为条件...
1、 Linux 中EXPORT_ SYMBOL 的用法 EXPORT_ SYMBOL 标签内定义的函数对全部 内核 代码公开,不用修改 内核 代码就可以在您的 内核模块 中直接调用。您还可以手工修改 内核 源代码来导出另外的函数,用于重新编译并 加载 内核 后的测试。 //mod1.c 编译 模块 mod2,成功。 加载 mod2时,输出: insmod: error inserting 'mod2.ko': -1 Inva li d parameters dmesg查看: mod2: no symbol version for func
编译了自己的驱动,但是insmod出现问题: 第一个问题: [ 12.722535] sciu2s: module verification failed: signature and/or required key missing - tainting kernel [ 12.722560] sciu2s: Unknown symbol usb_serial_deregister_...