arm上加载insmod驱动时出现Unknown symbol in module

加载cfg80211出错:insmod: can‘t insert ‘cfg80211.ko‘: unknown symbol in module, or unknown paramet 成功加载,只是没找到regulatory.db文件,问题不大,再看看识别到加载到内核的网卡没有。试过很多方式还是出现这样的报错,最后就想着直接加载进内核算了。看着报错的内容和RFKILL有关,那多半就是这个没配置好。也给编译进内核,然后cfg80211就可以编译进内核。在加载cfg80211.ko文件时出现报错。然后发现居然缺少配置,那就加上配置看看。linux内核版本:6.1.11。烧录进开发板,查看内核信息。 阅读详情

arm上加载insmod驱动时出现Unknown symbol in module

这几天在arm上做蓝牙耳机驱动的时候,编译好了驱动但是在板子上insmod时候。
这里写图片描述
怎么会出现这种情况,不对呀,仔细查我们会发现,其实编译驱动的时候,就出现了一些警告,只是当时没有在意而已,而恰恰是这些警告导致的这些问题。

硬件设备
板子用的是realarm
内核linux-2.6.35
交叉编译器arm-linux-gcc 4.4.3

问题解析


究其原因,其原因就是我们的驱动找不到内核的几个函数,我们可以看到我们找不到的函数有两个,一个是kill_proc_info 一个是snd_hwdep_new 。

问题来了,我们内核编的好好的怎么会找不到这两个函数呢

System.map与内核符号表


亲自编译过linux内核的可能编译完内核都会发现在生成vmlinuz的同时,生成一个System.map文件。

nm /boot/vmlinux > System.map
  • 1

通常我们会把发送到标准输出设备的链接映象信息重定向到一个文件中(如System.map)。编译内核时,System.map文件用于存放内核符号表信息。符号表是所有内核符号及其对应地址的一个列表,随着每次内核的编译,就会产生一个新的对应System.map文件,当内核运行出错时,通过System.map中的符号表解析,就可以查到一个地值应的变量名,或反之。

利用System.map,在内核或相关程序出错时,就可以获得我们比较容易识别的信息。

System.map位于使用它的软件(例如内核日志记录后台程序klogd)能够找到的地方。在系统启动时,如果没有以一个参数的形式为klogd给出System.map的位置,则klogd会在三个地方寻找System.map:

/boot/System.map
/System.map
/usr/src/linux/System.map
  • 1
  • 2
  • 3

尽管内核本身实际上不使用System.map,但其它程序,像klogd、lsof、ps以及其它像dosemu等许多软件

都需要有一个正确的System.map文件。利用该文件,这些程序就可以根据已知的内存地址查找出对应的内核变量名称,便于对内核的调试工作。

首先我们可以查看下我们需要的函数是否导入到符号表中System.map
使用如下命令查看cat -n System.map | grep kill_proc_info 和 cat -n System.map | grep snd_hwdep_new
这里写图片描述
我们发现函数snd_hwdep_new这个函数不在内核中,但是kill_proc_info已经在符号标志中,也就是已经编译在内核里面了,但是为什么内核还是找不到它呢,没事我们逐个解决。

EXPORT_SYMBOL


EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。

2.6以后的内核就必须用EXPORT_SYMBOL() 来导出来(因为2.6默认不到处所有的符号)。
EXPORT_SYMBOL的作用是什么?
EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。
这里要和System.map做一下对比:
System.map 中的是链接时的函数地址。链接完成以后,在2.6内核运行过程中,是不知道哪个符号在哪个地址的。

EXPORT_SYMBOL 的符号, 是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。而模块在加载过程中,其本质就是能动态连接到内核,如果在模块中引用了内核或其它模块的符号,就要EXPORT_SYMBOL这些符号,这样才能找到对应的地址连接。

使用需要三个步骤
第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
第二、在掉用该函数的模块中使用extern对之声明
第三、首先加载定义该函数的模块,再加载调用该函数的模块

另外,在编译调用某导出函数的模块时,往往会有

WARNING: "****" [**********] undefined!
  • 1

这个正好就是我们编译驱动时出现的那个警告

解决kill_proc_info


问题解析


kill_proc_info这个函数已经编译进了内核(在符号表中有这个函数),但是模块仍然找不到地址,这个说明一个问题,就是我们的函数kill_proc_info并没有被导出,也就是加载模块时候,模块驱动找不到地址。

我们查找一下内核源码中,所有出现kill_proc_info 的地方
这里写图片描述
我们会发现没有EXPORT_SYMBOL 的记录,也就是说**该函数的确没有导出, 即外界不可访问。
那么我们就按照那三个步骤我们以此查找

在模块函数定义之后使用EXPORT_SYMBOL(函数名)


首先我们找到定义函数的地方,前我们已经用grep -r kill_proc_info * 查找内核源码中所有出现kill_proc_info的地方。
我们可以看到其声明在include/linux/sched.h 定义在kernel/signal.c 中
其声明的函数原型为

extern int kill_proc_info(int, struct siginfo *, pid_t);
  • 1

那么我们就在kernel/signal.c 文件中函数定义之后添加如下代码

EXPORT_SYMBOL(kill_proc_info);
  • 1

在掉用该函数的模块中使用extern对之声明


然后我们在自己的模块中,调用该函数之前,声明此函数,声明如下

extern int kill_proc_info(int, struct siginfo *, pid_t);
  • 1

重新编译内核和我们的驱动模块


最后我们重新编译内核和我们的驱动模块,我们可以发现我们的

WARNING: "****" [kill_proc_info] undefined!
  • 1

这个警告消失了,同时我们再次查找kill_proc_info 的信息,我们可以看到,除了EXPORT_SYMBOL的信息,System.map中也多了几项关于kill_proc_info的信息
这里写图片描述

解决snd_hwdep_new


问题解析


对于snd_hwdep_new 我们采用同kill_proc_info 同样的方法逐个排除其原因
这里写图片描述
我们发现该函数

声明在include\sound/hwdep.c
定义在sound/core/hwdep.c
已经被EXPORT_SYMBOL导出
符号表System.map中没有这个函数

这个说明我们的函数所属的模块在内核编译的过程中,没有被编译进内核中。 这样我们的驱动模块使用它的函数同样找不到地址。

查找所属模块


那么我们来确认一下我们推断的正确性。

我们需要查找到该函数所属的模块,然后到该模块sound/core下,查看Kconfig和Makefile的信息。

首先进入该模块sound\core,源代码文件为hwdep.c,那么目标代码很有可能就叫做hwdep.o,我们看目录下有没有这个目标文件
这里写图片描述
很明显没有,但是我们并不能保证它就没有参与编译,因为它编译的目标文件也有可能不是hwdep.o , 这个依赖关系我们可以到Makefile中查找。
这里写图片描述
很明显编译后,的确会生成hwdep.o
而且我们也发现,这个配置信息是CONFIG_HW_DEP
那么我们就去Kconfig中查找这个变量的配置
这里写图片描述

我们可以发现这个模块属于ALSA SOUND,那么我们就好解决了,可以有多种方案实现
,其实解决方案的本质是一样的,

一个是直接修改配置文件Kconfig,使其编译进去内核
一个是使用make menuconfig或者其他配置工具,选择编译所属模块

我选择了第一种,因为我们现在已经找到了其Kconfig配置所在的位置,直接修改即可,选择第二种,方案的话往往不好取舍。

配置编译


我们在模块配置的地方加入default y
意为在编译内核的时候,直接将模块编译进内核,
这就相当于在make menuconfig的时候在该模块的地方选择y(或者*)

这里写图片描述

重新编译内核和我们的驱动模块


最后我们重新编译内核和我们的驱动模块,我们可以发现我们的

WARNING: "****" [snd_hwdep_new] undefined!
  • 1

这个警告消失了,同时我们再次查找snd_hwdep_new 的信息,我们可以看到,除了EXPORT_SYMBOL的信息,System.map中出现关于snd_hwdep_new的信息
这里写图片描述

总结


出现Unknown symbol in module,其本质就是模块在加载过程中,找不到函数的地址

那么我们就查找System.map和函数声明和定义的地方时候用EXPORT_SYMBOL

然后确认其具体出现原因,一般有两个

①函数未被EXPORT_SYMBOL,导致加载时找不到链接地址
②函数所在模块未被编译到内核中,导致加载时找不到链接地址

我们逐个排查,找出原因所在后,逐个解决即可,完成后重新编译内核已经驱动模块。
但是要注意如果您依赖的函数也是一个驱动模块,则应该首先加载定义该函数的模块,再加载调用该函数的模块

xxx.ko 驱动模块加载报错 “unknown symbol in module or invalid parameter” 在对单独驱动模块进行测试时,我们要进行动态编译,生成对应驱动的.ko模块。然后进行手动加载和卸载。但是在进行驱动模块加载时遇到了unknown symbol in module or invalid parameter问题,对此进行排查解决。 阅读详情

相关推荐

别光会insmod!运维排查Linux驱动加载失败,先学会用nm和readelf查ko文件‘底细’

本文深入探讨了Linux内核模块加载失败的排查方法,重点介绍了如何使用nm和readelf工具分析ko文件。通过解析ELF头信息、检查符号表以及重建编译环境,帮助运维人员快速定位驱动加载失败的根本原因,提升故障排查效率。

weixin_28681255的博客 308

"Unkown symbol in module"

在insmod uvcvideo.ko时,出现"Unkown symbol in module"错误.原因一般有二:1.其依赖的其他模块没有被装载.2.其依赖的其他模块已被替换,跟其版本等不匹配. 在ubuntu更新的kernel里,因为default没有装载v4l2相关的模块,所以需要手动安装.或者直接执行make install,然后modprobe uvcvideo.

May.Ouyang的专栏 3241

香橙派Zero2嵌入式开发:交叉编译、内核定制与驱动开发实战

嵌入式Linux开发的核心在于构建针对特定硬件平台的定制化软件生态。其基本原理是通过交叉编译,在x86主机上生成ARM架构的可执行程序,从而解决目标平台资源受限的问题。这项技术的核心价值在于能够高效地为嵌入式设备定制内核、优化功能并开发专用驱动,广泛应用于物联网、智能硬件和工业控制等领域。以香橙派Zero2(全志H616)为例,从搭建ARM64交叉编译工具链开始,到获取和配置官方内核源码,再到编译内核镜像、设备树和模块,最终完成系统镜像的更新。整个过程涉及**内核编译**和**驱动开发**两个关键环节,通过

weixin_33924220的博客 631

【Linux】【问题处理】insmod: ERROR: could not insert module xxx.ko: Unkown symbol in module问题的分析思路及解决方案

- 在嵌入式Linux开发过程中,经常遇到模块加载时提示“insmod: ERROR: could not insert module xxx.ko: Unkown symbol in module”的问题,本文将对此问题的分析和处理做一梳理,供各位参考。

一介草民,只为生活。 9892

NXP Layerscape Linux内核定制与eDMA/CAAM DMA驱动开发实战指南

在嵌入式Linux开发中,内核与驱动是连接硬件与应用的核心,其稳定性直接决定了系统的性能表现。Linux内核通过模块化的驱动框架管理硬件资源,而DMA(直接内存访问)技术则是提升数据传输效率、降低CPU负载的关键机制。其原理在于允许外设控制器在不经过CPU干预的情况下,直接在内存与I/O设备间搬运数据,从而释放CPU算力用于其他任务,这对于网关、边缘计算等对实时性和吞吐量有高要求的场景至关重要。本文聚焦于NXP Layerscape系列处理器平台,深入解析如何从源码获取、交叉编译环境搭建、内核配置系统(Kb

chiyingliao3565的博客 965

EXPORT_SYMBOL解析

一般我们编写C程序是,要调用某个文件中的函数,需要在本文件中包含声明有被调用函数的头文件,然后编译连接后,方能找到调用函数。对于模块依赖的情况,不能简单的使用上面的方法,内核提供了一个机制,就是EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。您还可以手

fulinux的博客 2893

insmod: can't insert './drivers/galcore.ko': unknown symbol in module, or unknown parameter

参考:linux内核插入模块时 Unknown symbol in module 参考:arm上加载insmod驱动时出现Unknown symbol in module 参考:加载内核模块-Unknown symbol错误分析 安装驱动: (1)编译linux内核 (2)编译驱动 (3)安装驱动 /mnt/mnt1/sdk # insmod ./drivers/galcor...

A person does not really understand something until after teaching it to a computer. Donald.E.Knuth 2366

详细了解sklearn中的CountVectorizer

CountVectorizer 是 scikit-learn(一个流行的 Python 机器学习库)中的一个文本特征提取类,其核心功能是将一系列原始文本(如句子、文档)转换为基于词频(word count)的数值矩阵。它基于词袋模型(Bag of Words, BoW)思想,忽略文本的语法结构和词序,仅关注词汇在文本中出现的频率,从而将文本转化为机器可理解的数字形式。文本 1:"I love machine learning"

2302_76568160的博客 1118

银河麒麟报错: insmod: ERROR: could not insert module pl2303.ko: Unknown symbol in module

这个pl2303在当前配置下(飞腾CPU+银河麒麟V10)的支持不是很好,经常是系统启动后没有加载成功,导致需要手动安装一遍。研究了一番,发现是usbserial模块没启动,导致pl2303驱动也无法安装。解决办法是先安装usbserial, 再安装pl2303。然后系统就能识别/dev/ttyUSB0了,问题解决。

小鹰信息技术服务部 1675

基于HPM5E00的EtherCAT从站开发实战:从硬件解析到软件调试

实时工业以太网通信是工业自动化与运动控制领域的核心技术,它通过硬件与协议栈的协同,实现了微秒级的高确定性数据交换。其技术价值在于为多轴同步、机器人控制等复杂场景提供了高实时性、高同步精度的通信基础。在应用场景上,广泛服务于数控机床、包装机械、半导体设备等高端制造领域。本文聚焦于EtherCAT从站开发,深入解析了基于先楫HPM5E00高性能MCU与专用从站控制器(ESC)的硬件架构设计,并详细阐述了开源协议栈SOES的移植、对象字典配置以及过程数据(PDO)映射等核心软件实践,为开发者快速构建稳定可靠的实时

weixin_30915951的博客 501

《UDS/OBD诊断需求编辑工具》总目录

目录 1 基于CANdela Studio编辑CDD诊断描述文件 2 基于ODX Studio编辑ODX/PDX文件 2.1 编辑ODX-D诊断描述文件 2.2 编辑ODX-F刷写软件 该专栏主要负责介绍CANdela Studio和ODX Studio编辑CDD/ODX/PDX诊断描述文件。 1 基于CANdela Studio编辑CDD诊断描述文件 2 基于ODX Studio编辑ODX/PDX文件 【ODX介绍 】-1- 标准梳理 【ODX介绍】 -2-如何手..

「汽车电子助手」的博客 1万+

insmod底层内存机制深度解析:从页表刷新到物理页分配

模块加载是Linux内核内存管理的关键入口,其本质是用户空间向内核空间安全映射代码与数据的过程。理解其原理需把握内存分层模型——从虚拟地址空间布局、页表项(PTE/PMD/PGD)动态构建,到TLB刷新开销、Buddy系统物理页分配及缓存一致性保障。在嵌入式场景中,insmod行为直接受限于RAM容量、内存对齐约束与架构特性(如ARMv7三级页表),一次加载可能触发隐式set_memory_ro、flush_tlb_kernel_range等高代价操作。本文聚焦内存视角下的全流程穿透,涵盖模块加载时的页表刷

weixin_30328063的博客 319

三臂杆大型液压机械臂集中式ADRC控制系统设计

本文设计了一种用于三臂杆液压机械臂的集中式自抗扰控制(ADRC)系统。该系统通过建立包含惯性矩阵、科氏力、重力及摩擦力的非线性动力学模型,并集成液压系统传递函数,构建了完整的系统模型。控制方案采用跟踪微分器安排过渡过程,扩张状态观测器实时估计系统状态和总扰动,以及非线性状态误差反馈生成控制量。MATLAB实现展示了集中式ADRC控制器的核心结构,包括参数定义、跟踪微分器、扩张状态观测器和非线性反馈模块的设计。该系统能有效处理多关节耦合效应,实现三输入三输出的MIMO控制,具有抗干扰能力强、响应速度快的特点。

huanghm88的专栏 269

零成本搭建QEMU ARM Linux驱动开发环境:从内核编译到字符设备驱动实战

嵌入式Linux驱动开发是连接硬件与操作系统的核心技术,其核心原理在于通过内核模块与硬件寄存器进行交互,实现对物理设备的抽象与管理。这项技术的价值在于为上层应用提供了统一、安全的硬件访问接口,是物联网、智能硬件等领域的基石。对于初学者而言,最大的障碍往往是硬件成本与调试风险。通过虚拟化技术,可以在标准PC上模拟完整的ARM开发环境进行学习与实践。QEMU作为一款强大的开源模拟器,能够仿真包括ARM Cortex-A系列在内的多种处理器架构,配合交叉编译工具链,可以完成内核编译、根文件系统制作等核心任务。本文

weixin_30520015的博客 355

2024年全国青少年信息素养大赛复赛真题(算法创意实践挑战赛C++试卷:带解析)

2024年全国青少年信息素养大赛复赛真题(算法创意实践挑战赛C++试卷:带解析)

王老师青少年编程 4784

C#对接EtherNet/IP协议 完整版|罗克韦尔AB PLC通信+CIP核心概念全解析

你做罗克韦尔(AB) PLC工业上位机开发,是唯一的首选协议,没有之一!EtherNet/IP(Ethernet Industrial Protocol)是基于标准以太网的工业级通信协议,由罗克韦尔自动化主导开发,是ODVA(开放设备网络供应商协会)主推的工业以太网标准,也是目前全球应用最广泛的工业以太网协议之一。原生适配罗克韦尔AB PLC:Micro800、CompactLogix、ControlLogix、Micro850等全系AB PLC原生标配EtherNet/IP,无需额外配置,开箱即用;

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 889

2.6.28内核中安装sctp模块的 问题

曾经在之前的较早的几个内核版本(2.6.12 和2.6.18)中修改过sctp的代码,当时编译sctp模块就直接用make CONFIG_IP_SCTP=m -C /usr/src/linux-2.6.28 M=/usr/src/linux-2.6.28/net/sctp modules然后insmod sctp.ko就ok了但是在比较新的内核2.6.28中,修改了部分 源代码

Macross的专栏 6487

循环神经网络(RNN)原理及BPTT算法

因循环神经网络基于ANN之上,理解ANN有助于理解RNN,所以阅读此文,建议先阅读。

L 1768

深入理解Linux模块——第1章 Hello World内核模块:内核编程的第一步

本文介绍了Linux内核模块的基本概念和开发入门。内核模块是一种动态加载的目标文件(.ko),解决了传统静态编译内核带来的镜像过大、内存浪费和更新麻烦等问题。文章通过一个简单的"Hello World"模块示例,详细讲解了模块的初始化/退出函数、许可证声明、作者信息等关键要素,并提供了对应的Makefile模板。示例代码展示了printk日志打印、模块信息宏使用等核心技巧,适合i.MX6ULL开发板环境。该教程旨在帮助开发者理解内核模块的本质,而不仅是复制粘贴代码,为后续更复杂的内核开发

charlie114514191的博客 586

Unreal5从入门到精通之初学者碰到解决不了的问题怎么办?

在学习Unreal的过程中,你曾陷入困境了吗?对于我来说,这种情况发生得比我愿意承认的要多得多。幸运的是,除了一般地在网上搜索之外,还有很多地方可以获得虚幻引擎的帮助。

TxNet 978

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Ubuntu 20.04下,手把手教你搞定移远RM500U-CN 5G模块的USB串口驱动(附内核编译避坑指南)

当你兴奋地将RM500U-CN 5G模块插入Ubuntu 20.04的USB接口,准备开始物联网项目时,却发现系统无法识别串口设备——这种挫败感我深有体会。本文将带你深入Linux内核驱动层,从原理到实践彻底解决这个问题,不仅让你成功驱动设备,更能理解背后的工作机制。在多次项目实践中,我发现最稳定的方案是将定制驱动通过DKMS集成到系统中。提示:不同批次的RM500U-CN可能有不同的产品ID,务必通过lsusb确认你的实际设备ID。在Ubuntu系统中,USB转串口设备的识别依赖于内核中的。

【洪波@阿里云】 486

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

嵌入式 Linux 驱动开发与内核更新全流程指南

2.3.4.5.

weixin_58988172的博客 365

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

RedwoodJS 自定义 Serverless Function 实战指南:从 `yarn rw generate function` 到部署与 CORS 排查

在 RedwoodJS 中,你在 Web 端发起的每一次 GraphQL 请求,底层其实都在调用 API 侧的 serverless Function(大写 F 的 Function,区别于 JavaScript 的 `function`)。这类 Function 面向 AWS Lambda 等 Serverless 平台设计部署,Redwood 沿用了 Netlify 的命名习惯称其为 Func

gitblog_01015的博客 316

简单三步解决Linux无线网卡兼容问题:rtl88x2bu驱动完整指南

你是否在Linux系统上遇到过Wi-Fi适配器无法识别或连接不稳定的问题?特别是在使用Realtek 88x2bu芯片的无线网卡时,系统自带驱动常常无法正常工作。rtl88x2bu开源驱动正是为解决这一痛点而生,它为Linux用户提供了稳定可靠的Wi-Fi连接解决方案。 ## 痛点分析:Linux用户的无线连接困境 在Linux系统中使用某些Wi-Fi适配器时,用户经常会遇到以下问题: >

gitblog_00376的博客 698
上一篇: Qt 动态库的编译和使用
下一篇: arm开发板 qt5.6.0 qt使用文泉驿字体
不是很大锅
博客等级 码龄10年 34粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值