您的位置:首页 > 运维架构 > Linux

加载中断模块错误提示:Unknown symbol in module

2017-01-24 11:09 806 查看
第一次写博客,分享心得。

在学习内核驱动时,韦东山老师所用的内核版本是2.6.26,我的内核版本是2.6.32。因为烧写进开发板的内核映像就是2.6.32的,为了保持版本号一致,就没有跟随老师用同一个版本。学习过程中就会遇到所讲课内容和我的内核内容冲突的问题,例如有的宏或者函数在2.6.26中有定义,但是在2.6.32中就取消了或者采用其他的定义方式。这样就需要自己深入内核代码中去查找差异,可以比较当前内核中自带的函数如何处理类似的问题。

我在学习按键中断驱动时就遇到了这样的问题,尝试各种办法,最终得以解决,分享一下。

第一次make时出现错误提示:

error:implicit declaration of function 'request irq',

提示说request_irq这个中断注册函数定义模糊(不知道标准的翻译是什么,我的理解如此)。于是在《Linux设备驱动程序》中查找到了request_irq的函数定义:

int request_irq(unsigned int irq,

irqreturn_t (*handler)(int , void *, struct pt_regs *), 

unsigned long flags, 

const char *dev_name,

 void *dev_id);

然后我就把这段函数定义加入到驱动程序中,竟然编译成功(当然会有一些警告)。之所以说竟然,是因为我之后看到这个定义是属于2.4内核的,2.6中定义是不一样的。当然也尝试了用2.6中的定义,下面会提到。错误更多,就没有再次罗列。

难得生成的.ko文件,立刻下载到开发板上加载,果然好景不长。又出现了问题:

insmod: cannot insert 'button_drv.ko': unknown symbol in module or invalid parameter

到底是模块出问题,还是内核。于是百度搜索了一些,也有碰到类似问题,最后的解决办法是加入'GPL',但是我的认证是加过的。然后看到有提到开发板内核和加载内核方式不同的问题,因为我下载到开发板的内核映像是出厂光盘里跟的。于是我再次在2.6.32内核中make uImage,最后把生成的映像下载到开发板。再次加载模块发现并无济于事!还是出现一样的错误。

冷静下!

仔细想一下,可以编译并不代表可以加载进内核。一定是内核在尝试运行这个模块时,出现了无法识别的东西,有可能就是request_irq这个注册函数的定义出了问题!再次用Source Insignt钻进2.6.32的内核代码中,搜索查找分析,不能再盲目的粘贴函数定义。链接到request_irq函数定义如下:

extern int __must_check

request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
    const char *name, void *dev);

这是2.6中的函数定义,当然开始我也傻乎乎的把它加到了驱动中,前面提到了,最后错误百出。最终发现,我忽略了一个重要问题:头文件!这段函数定义是在<linux/interrupt>中定义的,于是我把头文件添加在驱动程序中,编译和模块加载都通过了。

查看教程中的程序,却没有包含这个头文件,却可以编译加载通过。看来2.6.32相对2.6.26对函数定义出现了更新,内核的更新带来定义的不同,以后或许还会碰到类似问题。韦老师传授的方法是不合理的,他说看别人用了什么头文件我们就用什么,这种方法虽然可以奏效,但是自己并不知道哪个函数需要哪个头文件。一股脑放进去,不仅会造成代码冗余,还是影响可读性。

小建议:学习中遇到问题首先不应该想着问别人或者百度,可以自己尝试解决。英文提示看不懂就挨个单词查看,错误提示也是内核中编译进去的,就会用一定编写规则,同样一句话就可能出现多次,看多了就熟悉问题出在哪里了。如果只是一味的寻求帮助,就丧失了自主解决问题的能力,这并不是作为一个研发人员应有的职业素养。扯远了......继续学习,共同进步!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 函数 内核
相关文章推荐