前言
-
最近遇到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
加载命令加载,也可以在内核启动后使用自动加载脚本加载模块