• 嵌入式Linux 开发经验:内核驱动静态编译与模块编译


    前言

    • 最近遇到Linux 开发板网络不通的问题,问题为:自己编译的Linux内核烧写后网络驱动异常,无法联网,而官方给的编译好的Linux 内核文件,烧写后能正常的联网。虽然有点怀疑官方给的Linux 内核代码可能不是最新的,但是这个问题还是需要排查定位一下。

    • 今天花了一些时间,认真的排查一下,终于找到了原因所在,解决了网络不通的问题,所以记录一下问题排查思路,虽然走了弯路,不过有一点所得。

    开始排查

    • Linux 内核的烧写,我用到 shell 脚本,这样方便,否则需要输入几条 shell 命令才能编译,shell 执行脚本的config 配置,来自开发板的 defconfig,没有使用 make menuconfig 更改

    • 查看Linux 内核代码发现这个开发板有好几个默认的defconfig 配置文件,所以更换另一个defconfig 文件编译,确认是否有所进展。

    • 验证结果:更换defconfig 配置文件编译后的内核,下载到开发板,网络功能正常,可以获取IP 并且能ping 通外网

    • 【问题初步定位】,与config 配置有关系

    • 通过对比两个defconfig 文件,发现有点不同。网络功能正常的defconfig 文件,网络驱动部分配置使用的是静态编译 [*]方式,网络异常的defconfig 文件,网络驱动部分配置使用的模块化编译[M]方式。还有一个不同点:网络功能正常的,网络驱动配置多开启了一个 网络PHY 的驱动

    • 问题原因:要么两者都有效,要么只有其中一个修改有作用

    问题定位

    • 通过步骤一,我把网络有问题的网络驱动部分的配置,更改成网络正常的网络驱动配置,验证结果是:能正常联网。这说明,【静态编译】与【多开启一个PHY驱动】,两个中至少有一个修改解决了网络不通的问题

    • 还是想进一步排查,到底是【静态编译】造成的还是【多开启一个 PHY】驱动引起的,因为静态编译与【模块编译】,感觉应该不是问题,网络PHY 驱动的影响应该是很大的。

    • 【继续排查】:只增加网络PHY驱动,结果出乎意料:网络还是不能正常工作。说明不是网络PHY 驱动造成的,理论上就只有【静态编译】造成的原因了。

    • 网络驱动配置使用【静态编译】,不增加网络PHY 驱动,编译烧写后,发现网络正常,这就锁定了原因:【静态编译】能解决网络不通问题

    问题分析

    • 【静态编译】,确实解决了网络问题,但是这个结果有点意外,为何【模块编译】影响网络功能了呢?

    • 忽然想到一个【问题】,【静态编译】与【模块编译】的不同点,也就是模块编译的驱动,驱动一般是 *.ko文件,没有编译进内核,而我排查问题时,只更新了内核文件,没有更新这个新编译的内核驱动模块 *.ko文件。

    • 无法联网问题,大概率就是*.ko 驱动文件没有更新造成的

    继续验证

    • 通过find 查找,发现【模块编译】后生成了网络驱动模块的 ko 文件

    • 开发板开机后就能自动加载的网络驱动,说明有个自动加载脚本在启动时加载了网络驱动模块 ko 文件,在开发板的根文件系统查找,最终找到了这个默认的网络驱动模块 ko文件

    解决方法一

    • 就是上面的【静态编译】,静态编译的内核文件,烧写后网络功能正常,当然也说明Linux 内核网络驱动代码是OK的

    解决方法二

    • 内核的驱动配置【模块编译】不需要更改,只需要把编译新生成的网络驱动模块 ko 文件,替换开发板默认的网络驱动模块ko文件即可。替换网络驱动模块后并重启,发现开发板的网络功能正常了

    遗留问题

    • 官方给的编译好的内核文件,为何网络功能是正常的?难道网络驱动配置是静态编译的?这个后续继续研究与排查

    小结

    • 通过排查Linux 网络驱动,发现自己对Linux 驱动【静态编译】【模块编译】方式了解的不够深入,忽略了【模块编译】后,驱动模块没有编译进内核,需要把生成的模块ko文件,手动烧写进开发板,加载到内核才能工作

    • 【静态编译】配置的驱动,编译时驱动会与内核一起编译成一个文件,只需要烧写内核,驱动就可以工作。【静态编译】的内核网络功能正常,也可以说明这个内核网络驱动代码的是正常的。

    • 【模块编译】 配置的驱动,好像驱动只是占了位,驱动代码没有编译进内核,通过 make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build modules -j4 生成 了模块文件 xxx.ko ,这个模块文件xx.ko 要手动放进开发板的文件系统中,放在指定的位置,让内核加载才能工作,可以手动使用 insmod modprobe 加载命令加载,也可以在内核启动后使用自动加载脚本加载模块

  • 相关阅读:
    QUIC协议包头保护(四)
    算法通关村17关 | 盘点面试大热门之区间问题
    【C++风云录】解锁智慧之门:物联网安全工具和库助力打造安全可靠的智能家居
    eclipse-向Console控制台输出信息
    java 选择排序
    十三、企业开发(1)
    Unity 鼠标拖拽旋转平面内2D物体 解决方案
    当涉及到PDF中的数据挖掘,PDFPlumber是您的得力助手
    git问题,分支直接的提交切换
    java中的interface(接口)
  • 原文地址:https://blog.csdn.net/tcjy1000/article/details/128045222