Linux 驱动之EXPORT_SYMBOL 函数以及2.6内核 Unknown symbol bug解决办法

1、Linux中EXPORT_SYMBOL的用法

EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用。您还可以手工修改内核源代码来导出另外的函数,用于重新编译并加载新内核后的测试。

//mod1.c

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

MODULE_LICENSE("DUAL BSD/GPL");

int func1(void)
{
        printk("In Func: %s.../n",__func__);
        return 0;
}
static int __init hello_init(void)
{
        printk("Module 1,Init!/n");
        return 0;
}

static void __exit hello_exit(void)
{
        printk("Module 1,Exit!/n");
}

EXPORT_SYMBOL(func1);

module_init(hello_init);
module_exit(hello_exit);

//mod2.c

#include<linux/init.h>

#include<linux/kernel.h>

#include<linux/module.h>

MODULE_LICENSE("DUAL BSD/GPL");

extern int func1(void);

static int func2(void)

{

func1();

printk("In Func: %s.../n",__func__);

return 0;

}

static int __init hello_init(void)

{

printk("Module 2,Init!/n");

func2();

return 0;

}

static void __exit hello_exit(void)

{

printk("Module 2,Exit!/n");

}

module_init(hello_init);

module_exit(hello_exit);

//Makefile

ifneq ($(KERNELRELEASE),)
obj-m   := xxx.o
else
KDIR    := /lib/modules/$(shell uname -r)/build
PWD             := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
	rm -rf Module.symvers *.ko *.o *.mod.c .*.cmd .tmp_versions *~ *.*~

endif

2、 运行

有两个模块,mod1和mod2。

在mod1中定义了func()1函数,并且经EXPORT_SYMBOL()导出。

在mod2中extern func()1,调用func()1。

①insmod mod1.ko

②insmod mod2.ko

编译模块mod2,成功。

加载mod2时,输出:

insmod: error inserting ‘mod2.ko‘: -1 Invalid parameters

dmesg查看:

mod2: no symbol version for func

mod2: Unknown symbol func (err -22)

③cat /proc/kallsyms |grep func1

了解了什么是内核符号表之后,我们回到之前的问题。

我们查看/proc/kallsyms,发现mod1的func函数的标志为t,而此标志表示函数是局部的。

此问题是内核2.6.26之后版本的bug,并且不会被修复

3、解决办法

(1)把mod1的Module.symvers放到mod2中,这样在编译mod2时符号信息会自动链接进去。

(2)在mod2的Makefile中添加符号信息

echo ‘0x01873e3f        func  mod1 EXPORT_SYMBOL_GPL‘ > Module.symvers

这样mod2在编译时就知道mod1中func符号的地址。

Q:这个问题是由什么引起的呢?

A:生成mod2的时候不知道mod1中func的校验码,mod2加载时检查校验码出错。

在内核主线代码树的一个提交修改了内核挂载模块时的函数版本校验机制,使得在挂载模块时候对于编译

时个别函数没有确定CRC校验值无法通过check_version函数检查。

这是内核有意要禁止存在个别无版本校验信息的函数的模块挂载。

时间: 2024-10-11 01:33:21

Linux 驱动之EXPORT_SYMBOL 函数以及2.6内核 Unknown symbol bug解决办法的相关文章

Linux驱动学习之Linux-2.6.20.4内核移植

最近一段时间一直在学习向TQ2440开发板移植内核.移植驱动.真心觉得这方面的知识有很大的难度.但是从另一角度去看,难度越大,能力提升的空间就越大!! 1.解压源码 从网上下载一个Linux 内核,我是用的是Linux-2.6.20.4.然后用命令解压.建议解压到"/home/用户名"目录下.我的内核源码存放在: 2.添加对ARM的支持 因为所用的是TQ2440开发板,属于ARM9.因此要在系统中添加对ARM的支持. 方法:进入内核源码目录, 修改"Makefile"

linux中ERROR: The partition with /var/lib/mysql is too full!解决办法

今天在ubuntu上遇见这个问题.应该是我的第一分区太小了. 解决办法: [email protected]:/var$ cd /var [email protected]:/var$ rm -rf log 我们删除日志文件 [email protected]:/var$ /etc/init.d/mysql start 在开启mysql就正常了 linux中ERROR: The partition with /var/lib/mysql is too full!解决办法,布布扣,bubuko.c

关于MATLAB中xlswrite函数写数据出现服务器异常情况的解决办法

在网上找了半天解决办法,也没有找到,在此共享我自己的一个问题,不具有普遍性,仅作参考! 问题描述:MATLAB调用xlsread函数出现问题,第一次运行的时候,出现服务器异常,再次运行能够正常读取数据: 在调用xlswrite函数时,一直出现服务器异常状况,不能将数据写入excel表格中. 问题关键:不是MATLAB的原因,问题出在excel软件上! 问题解决:xlswrite函数在调用时会占用excel的com端口,所以要保证在调用时这个端口是开放的,也就是没有被其他程序占用.打开excel(

Linux系统下不让MySQL区分表名的大小写的解决办法

问题描述: 今天将某项目数据库移植到liunix服务器上,结果出现无法找到表的错误,查询数据库,表确实是存在的.经过分析比较,发现是表名大小写问题导致. 问题分析: MySQL数据库的表名在Linux系统下是严格区分大小写的,在Windows系统下开发的程序移植到Linux系统下,如果程序中SQL语句没有严格按照大小写访问数据库表,就可能会出现找不到表的错误. 解决办法: 修改MySQL的配置文件my.cnf,在[mysqld]部分添加如下配置选项lower_case_table_names =

linux内核编译__devinit错误解决办法

linux kernel3.8以后,把: __devinit, __devinitdata, __devinitconst, __devexit, __devexitdata, __devexitconst 这些都去掉了. 出现的错误: __devinit error expected '=' ' ' ' ' 'asm' or '__attribute__' before 解决办法: #define __devexit#define __devinitdata#define __devinit

Linux进程的创建函数fork()及其fork内核实现解析

进程的创建之fork() Linux系统下,进程可以调用fork函数来创建新的进程.调用进程为父进程,被创建的进程为子进程. fork函数的接口定义如下: #include <unistd.h> pid_t fork(void); 与普通函数不同,fork函数会返回两次.一般说来,创建两个完全相同的进程并没有太多的价值.大部分情况下,父子进程会执行不同的代码分支.fork函数的返回值就成了区分父子进程的关键.fork函数向子进程返回0,并将子进程的进程ID返给父进程.当然了,如果fork失败,

Centos7升级内核后无法启动解决办法:mpt[23]sas驱动问题

参考链接:https://www.cnblogs.com/muahao/p/7610413.htmlCentOS 7.6 从内核 3.10.0 升级到 5.3.6后,重启不了,原因是 Linux 内核 4.4.x 版本之后,dracut 命令生成的 initramfs 默认不会自动加载 mpt3sas 驱动模块.因为没有对应的驱动程序,所以识别不了系统盘(两块 SAS 系统盘接在 LSI 2308 HBA 卡上,创建 RAID 1),从而导致内核 vmlinuz 无法加载它的 rootfs(根文

onclick函数中,取不到$(this)的解决办法

html: <a href="javascript:;" onclick="clickSearch('click',this);" >前端开发</a> JQ: function clickSearch(type,th) { if (type == "click") { alert($(th).html()) ; } } html中用this参数, 函数中用th传参使用.

Linux相关问题-CentOS6.5 x64版本下Tomcat无法自启动的解决办法

前段时间使用阿里云服务器,使用的是Linux CentOS6.5系统,在搭建完Tomcat后发现,Tomcat无法自启动, 将启动tomcat的命令为tomcat_home/bin/startup.sh或tomcat_home/bin/catalina.sh start,当直接把他们任何一个加入到/etc/rc.local中,发现问题仍然无法解决,故编写如下自启动脚本 export JAVA_HOME=/usr/local/jdk1.7.0_51 export PATH=$JAVA_HOME/b