最近遇到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
文件
ko
文件,替换开发板默认的网络驱动模块ko
文件即可。替换网络驱动模块后并重启,发现开发板的网络功能正常了通过排查Linux 网络驱动,发现自己对Linux 驱动【静态编译】【模块编译】方式了解的不够深入,忽略了【模块编译】后,驱动模块没有编译进内核,需要把生成的模块ko
文件,手动烧写进开发板,加载到内核才能工作
【静态编译】配置的驱动,编译时驱动会与内核一起编译成一个文件,只需要烧写内核,驱动就可以工作。【静态编译】的内核网络功能正常,也可以说明这个内核网络驱动代码的是正常的。
【模块编译】 配置的驱动,好像驱动只是占了位,驱动代码没有编译进内核,通过 make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=build modules -j4
生成 了模块文件 xxx.ko
,这个模块文件xx.ko
要手动放进开发板的文件系统中,放在指定的位置,让内核加载才能工作,可以手动使用 insmod
modprobe
加载命令加载,也可以在内核启动后使用自动加载脚本加载模块