内核驱动程序外部模块未完全构建
我正在将外部驱动程序模块添加到 android Gingerbread 内核(与 Linux 类似)。我以前做过并且有效,但这次我遇到了问题。我遵循 O'Reilly“Linux 设备驱动程序第 3 版”中的配方,即:
在本地 Makefile 中,添加这些语句:
obj-m := GobiNet.o GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
用人类语言来说,这意味着从 GobiUSBNet.c + QMIDevice.c + QMI.c 为我构建一个 GobiNet.ko。
这是针对构建整个内核时调用 makefile 的情况。我正在 Ubuntu x86-64 位上针对 ARM-EABI 系统 (Cortex-A8) 进行交叉编译。
不知何故,构建系统理解我想要什么,因为它在编译时说:
/home/sylvain/Projects/android_gingerbread_realv210_ver_1_0/kernel CHK include/linux/version.h CHK包括/生成/utsrelease.h make[1]: `include/ generated/mach-types.h' 是最新的。 调用脚本/checksyscalls.sh CHK include/ generated/compile.h LD 驱动程序/cell/OptionGobiNet/built-in.o CC [M] drivers/cell/OptionGobiNet/GobiUSBNet.o CC [M] drivers/cell/OptionGobiNet/QMIDevice.o CC [M] drivers/cell/OptionGobiNet/QMI.o LD [M] drivers/cell/OptionGobiNet/GobiNet.o 内核:arch/arm/boot/Image 已准备好 已发货 arch/arm/boot/compressed/lib1funcs.S AS arch/arm/boot/compressed/lib1funcs.o LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage 内核:arch/arm/boot/zImage 已准备就绪 构建模块,第 2 阶段。 MODPOST 5 模块 错误:“usbnet_suspend”[drivers/cell/OptionGobiNet/GobiNet.ko] 未定义! 错误:“usbnet_resume”[drivers/cell/OptionGobiNet/GobiNet.ko] 未定义! 错误:“usbnet_disconnect”[drivers/cell/OptionGobiNet/GobiNet.ko] 未定义! 错误:“usbnet_probe”[drivers/cell/OptionGobiNet/GobiNet.ko] 未定义! make[1]: *** [__modpost] 错误 1 make: *** [模块] 错误 2
它还生成典型的“GobiNet.mod.c”和“GobiNet.o”,当您希望驱动程序作为模块但它不符合我期望的“GobiNet.ko”时生成。我在主目录中运行了“find -name *.ko”,却找不到“GobiNet.ko”。
我还查看了 WEB 和 kernel/documentation/kbuild/*.txt。大约有 3 种方法可以做到这一点。我选择了上面描述的一种,因为所有环境变量都是在顶部构建脚本中设置的,并且我不编译本机,但我交叉编译。无论如何,内核树中的其他“.ko”已生成,因此构建脚本应该可以很好地生成“.ko”模块。
知道是什么让这个过程开始但不以“.ko”文件结束吗?
I'm adding an external driver module to an android Gingerbread kernel (works similar to Linux). I've done it before and it worked but I have a problem this time. I follow the recipe found in O'Reilly "Linux Device Drivers 3rd edition" which is:
in the local Makefile, you add those statements:
obj-m := GobiNet.o GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
In human language it means build me a GobiNet.ko from GobiUSBNet.c + QMIDevice.c + QMI.c.
This is for the case where the makefile is called when building the whole kernel. I'm cross-compiling on a Ubuntu x86-64bit for an ARM-EABI system (Cortex-A8).
Somehow, the build system understands what I want since it says during compile time:
/home/sylvain/Projects/android_gingerbread_realv210_ver_1_0/kernel CHK include/linux/version.h CHK include/generated/utsrelease.h make[1]: `include/generated/mach-types.h' is up to date. CALL scripts/checksyscalls.sh CHK include/generated/compile.h LD drivers/cell/OptionGobiNet/built-in.o CC [M] drivers/cell/OptionGobiNet/GobiUSBNet.o CC [M] drivers/cell/OptionGobiNet/QMIDevice.o CC [M] drivers/cell/OptionGobiNet/QMI.o LD [M] drivers/cell/OptionGobiNet/GobiNet.o Kernel: arch/arm/boot/Image is ready SHIPPED arch/arm/boot/compressed/lib1funcs.S AS arch/arm/boot/compressed/lib1funcs.o LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready Building modules, stage 2. MODPOST 5 modules ERROR: "usbnet_suspend" [drivers/cell/OptionGobiNet/GobiNet.ko] undefined! ERROR: "usbnet_resume" [drivers/cell/OptionGobiNet/GobiNet.ko] undefined! ERROR: "usbnet_disconnect" [drivers/cell/OptionGobiNet/GobiNet.ko] undefined! ERROR: "usbnet_probe" [drivers/cell/OptionGobiNet/GobiNet.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2
It also generates the typical "GobiNet.mod.c" and "GobiNet.o" that is generated when you want the driver as a module but it doesn't complete with the "GobiNet.ko" I would expect. I ran a "find -name *.ko" in the home directory and "GobiNet.ko" is nowhere to but found.
I also looked on the WEB and in the kernel/documentation/kbuild/*.txt. There is about 3 ways to do it. I chose the one described above because all the environment variables are set within the top build script and I don't compile native but I cross compile. Anyway, the other ".ko" in the kernel tree are generated so the build script should be good to generate the ".ko" modules.
Any idea what makes this process start but not finish with the ".ko" file?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我找到了解决方案。我真的误解了错误消息以及“.ko”模块如何与内核交互。外部模块在编译/链接时而不是在运行时解析外部(至少是一些)。这就是为什么我收到 4 个“错误”的原因。
也就是说,我的“GobiNet”正在寻找我的内核设置中不存在的外部符号。一些快速的 grep 让我找到它需要的“drivers/net/usb/usbnet.c”。这需要在“.config”文件中设置 CONFIG_USBNET = y(通过“make xconfig”设置)。希望它可以帮助别人。
编辑:回答有关“一些快速 grep”的问题。我的意思是我搜索包含丢失名称的所有源文件。它会告诉我哪个文件定义了该符号。然后,我可以找到应该将哪个变量设置为“y”以将其包含在编译中。这是一个示例:
您可以在终端中从要递归搜索的文件夹(-r 选项)执行该命令。 grep 对于在大量文件中查找文本非常有用。我经常不记得具体的内容,但快速的谷歌搜索可以让你如何执行一些非常棘手的搜索,你从未想过可以如此轻松地完成。
I found the solution. I really misunderstood the error messages and how ".ko" modules interact with the kernel. An external module resolves externals (at least some) at compile/link time not at run time. This is why I get the 4 "ERRORS".
That said, my "GobiNet" is looking for external symbols not present in my Kernel set-up. A few quick greps allowed me to find it needed "drivers/net/usb/usbnet.c". This required CONFIG_USBNET = y to be set in the ".config" file (set through "make xconfig"). Hope it can help someone else.
EDIT: To answer the question about "a few quick greps". What I meant is I search all the source files containing the missing names. It will tell me what file defines that symbol. Then, I can find what variable should be set to "y" to include it in the compile. Here is an example:
You execute that in the terminal from the folder you want to search from and down recursively (-r option). grep is extremely useful to find text in large amount of files. I often don't remember the specific but a quick Google search gives you how to perform some very tricky searches you never thought could be done so easily.
另一种可能性是函数已定义但未以某种方式导出(就像您编写自己的新函数但忘记导出,或者某些合并问题)。修复方法是添加一行,如
EXPORT_SYMBOL_GPL(some_new_func);
Another possibility is that the function is defined but not exported somehow ( like you write your own new function but forgot to export, or some merge issue). The fix is then add a line like
EXPORT_SYMBOL_GPL(some_new_func);