简介:本资源面向在银河麒麟V10国产操作系统上进行网卡适配的开发与运维人员,提供已在该系统下编译通过的e1000e与RTL8125两款网卡驱动源码。e1000e对应Intel 82573E、82574L等以太网控制器,RTL8125则针对Realtek RTL8125B/C千兆网卡,可解决国产系统与硬件适配中常见的编译报错与兼容性问题。压缩包共56个文件,以21个.h头文件、19个.c源文件为主,另含3个makefile及readme、spec、updates等构建与说明文件,整体约483KB,目录按驱动模块分开放置,便于对照内核版本调整。作者在源码层面删除了重复定义并修改了函数参数,使驱动能顺利通过银河麒麟V10内核编译,读者可直接参考其改动思路完成加载与验证。目前已有2735人学习下载,适合具备一定Linux驱动基础、需要快速完成网卡适配的开发者参考。
1. 银河麒麟 V10 下 e1000e 与 rtl8125 驱动编译:为什么源码包比官方源更值得折腾
在国产化替代的现场,银河麒麟 V10 桌面版和服务器版被大量部署在飞腾、鲲鹏、海光以及 Intel 平台上,网卡驱动却经常成为第一道拦路虎。Intel 的 e1000e 系列千兆网卡和 Realtek 的 rtl8125 2.5G 网卡,在麒麟自带的驱动库里要么版本偏旧,要么干脆没有对应模块,插上网线后ip link里看不到接口,或者能识别却频繁丢包。这份资源包提供的正是能在银河麒麟 V10 上直接编译通过的 e1000e 与 rtl8125 驱动源码,省去了从上游内核源码里翻找、打补丁、反复试错的环节。它适合两类人:一是刚接手国产化终端适配、需要快速让网卡跑起来的运维工程师;二是想搞清楚 Linux 驱动编译链路、不愿每次靠重装系统碰运气的技术爱好者。下面从源码结构、编译环境、参数配置到实际排错,一步步拆开讲。
2. 驱动源码包结构拆解:e1000e 与 rtl8125 的目录差异
拿到一个驱动源码包,先别急着make。不同厂商的代码组织方式差别很大,e1000e 是 Intel 官方维护的经典结构,rtl8125 则是 Realtek 在 r8169 基础上独立出来的分支,两者在 Makefile 写法、依赖头文件和固件加载逻辑上都有区别。搞清楚这些差异,后面编译报错时才能快速定位是缺内核头文件还是代码本身不兼容。
2.1 e1000e 源码目录与关键文件
Intel 的 e1000e 驱动通常包含以下核心文件:
| 文件名 | 作用 |
|---|---|
e1000e_main.c | 驱动入口,注册 net_device 和 PCI 设备 ID |
e1000e_hw.h | 硬件寄存器定义,与具体网卡型号强相关 |
e1000e_ethtool.c | 支持 ethtool 查询和设置 |
Makefile | 定义模块名和编译目标 |
kcompat.h | 兼容旧内核的宏定义,麒麟 V10 上经常需要改这里 |
麒麟 V10 的内核版本通常是 4.19 或 5.4 系列,e1000e 源码里如果带了kcompat.h,说明它已经为多内核版本做了适配。但要注意,部分从 Intel 官网下载的版本默认只支持到 5.x 的某个小版本,遇到麒麟的定制内核时,kcompat.h里的#if LINUX_VERSION_CODE判断可能走错分支,导致编译报错。
2.2 rtl8125 源码目录与 e1000e 的差异
Realtek rtl8125 的源码包通常长这样:
rtl8125/ ├── src/ │ ├── r8125_n.c # 主驱动文件,命名和 e1000e 完全不同 │ ├── r8125.h │ ├── r8125_firmware.c # 固件加载逻辑,e1000e 没有这个文件 │ └── Makefile └── README和 e1000e 最大的区别在于,rtl8125 驱动把固件加载逻辑单独放在r8125_firmware.c里,编译时如果内核没有开启CONFIG_FW_LOADER,会直接报unknown symbol request_firmware。另外,rtl8125 的 Makefile 里通常有CONFIG_ASPM、ENABLE_EEE等开关,这些在 e1000e 里是通过模块参数控制的,不是编译期选项。
提示:两个源码包不要放在同一个目录下编译,Makefile 里的
obj-m变量会互相覆盖,导致只生成一个.ko文件。
2.3 编译前必须确认的内核头文件路径
银河麒麟 V10 默认可能没有安装完整的内核头文件包。先执行:
uname -r # 输出示例:4.19.90-24.4.v2101.ky10.x86_64 ls /lib/modules/$(uname -r)/build # 如果提示 No such file or directory,说明缺内核头文件如果/lib/modules/$(uname -r)/build不存在,需要从麒麟的软件源安装kernel-devel或linux-headers包。常见做法是:
sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) # 或者 sudo apt install linux-headers-$(uname -r)具体用 yum 还是 apt,取决于你的麒麟 V10 是服务器版还是桌面版。服务器版默认 yum,桌面版可能预装了 apt 兼容层。装完后再次确认build软链接指向正确的内核源码目录,否则编译出来的.ko版本号会和当前内核不匹配,insmod时报invalid module format。
3. 编译环境搭建与 Makefile 参数调整
驱动编译不是make一下就完事,尤其是麒麟 V10 这种带定制补丁的内核,Makefile 里的路径和编译选项经常要手动改。这一章把 e1000e 和 rtl8125 的编译流程分开讲,因为两者的 Makefile 结构差异决定了改法不同。
3.1 e1000e 编译:从 Makefile 到 ko 文件
进入 e1000e 源码目录,先看 Makefile 开头:
# e1000e Makefile 片段 obj-m := e1000e.o e1000e-objs := e1000e_main.o e1000e_ethtool.o e1000e_netdev.o KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules关键参数说明:
obj-m:告诉内核构建系统这是一个可加载模块,不是内置驱动。KERNELDIR:指向当前内核的构建目录,如果麒麟 V10 的内核头文件装在非标准路径,这里要改成实际路径。M=$(PWD):指定模块源码所在目录。
编译命令:
make clean make # 成功后当前目录会出现 e1000e.ko如果报错error: implicit declaration of function ‘pci_alloc_irq_vectors’,说明麒麟 V10 的内核版本低于 4.8,而源码用了新 API。常见做法是在kcompat.h里加一个宏定义,把新 API 映射到旧函数:
// 在 kcompat.h 里补充 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) #define pci_alloc_irq_vectors pci_enable_msi_range #endif改完重新make,一般就能过。编译成功后用modinfo e1000e.ko确认版本和依赖,再sudo insmod e1000e.ko加载。
3.2 rtl8125 编译:处理固件依赖与 ASPM 开关
rtl8125 的 Makefile 通常更复杂,因为它带了一堆编译期开关。先看关键片段:
# rtl8125 Makefile 片段 obj-m := r8125.o r8125-objs := r8125_n.o r8125_firmware.o CONFIG_ASPM = y ENABLE_EEE = yCONFIG_ASPM控制是否启用 PCIe 主动状态电源管理,ENABLE_EEE控制节能以太网。在麒麟 V10 上,如果主板 BIOS 对 ASPM 支持不好,开启后会导致网卡频繁掉线。我一般会先把这两个开关关掉,等驱动稳定后再逐个打开测试:
make clean make CONFIG_ASPM=n ENABLE_EEE=n编译过程中如果报fatal error: linux/firmware.h: No such file or directory,说明内核头文件里缺固件加载相关的头。麒麟 V10 的kernel-devel包有时会裁剪掉这部分,需要手动从完整内核源码里拷贝firmware.h到/lib/modules/$(uname -r)/build/include/linux/下,或者安装linux-firmware包。
编译成功后,加载模块前先确认固件文件是否存在:
ls /lib/firmware/rtl_nic/rtl8125a-3.fw # 如果不存在,从源码包的 firmware 目录拷贝过去 sudo cp rtl8125/src/rtl8125a-3.fw /lib/firmware/rtl_nic/3.3 模块加载与开机自动生效
手动insmod只对当前会话有效,重启后失效。要让驱动开机自动加载,需要把.ko文件放到/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/对应目录下,然后执行:
sudo depmod -a sudo modprobe e1000e sudo modprobe r8125如果系统里已经有旧版驱动,modprobe可能会优先加载旧模块。这时需要把旧模块加入黑名单:
echo "blacklist e1000e" | sudo tee /etc/modprobe.d/blacklist-e1000e.conf echo "blacklist r8169" | sudo tee /etc/modprobe.d/blacklist-r8169.conf # 注意:rtl8125 和 r8169 会冲突,必须屏蔽 r8169改完后更新 initramfs:
sudo dracut -f # 或者 sudo update-initramfs -u重启后用ethtool -i eth0查看驱动版本,确认加载的是新编译的模块,而不是内核自带的旧版。
4. 避坑与常见问题排查:从编译报错到网卡不识别
驱动编译和加载过程中,报错信息往往很隐晦,尤其是麒麟 V10 的定制内核,很多错误不是代码本身的问题,而是环境配置或版本匹配的坑。下面整理 5 条实际踩过的记录,每条按现象、原因、解决来写。
4.1 编译时报 “Kernel configuration is invalid”
现象:执行make后提示ERROR: Kernel configuration is invalid. include/generated/autoconf.h or include/config/auto.conf are missing.
原因:内核头文件包只装了部分文件,缺少编译时生成的配置文件。麒麟 V10 的kernel-devel包有时不包含include/config/目录。
解决:从/boot/config-$(uname -r)拷贝配置文件到内核构建目录,然后手动生成:
sudo cp /boot/config-$(uname -r) /lib/modules/$(uname -r)/build/.config cd /lib/modules/$(uname -r)/build sudo make oldconfig sudo make prepare如果make prepare报缺脚本,说明内核源码不完整,需要安装完整的内核源码包,而不是只装kernel-devel。
4.2 insmod 报 “invalid module format”
现象:sudo insmod e1000e.ko返回insmod: ERROR: could not insert module e1000e.ko: Invalid module format。
原因:编译时用的内核版本和当前运行的内核版本不一致。常见于系统更新后没有重启,或者KERNELDIR指向了错误的内核源码目录。
解决:用modinfo e1000e.ko | grep vermagic查看模块的版本标记,和uname -r对比。如果不一致,清理后重新编译:
make clean make KERNELDIR=/lib/modules/$(uname -r)/build确保编译环境和运行环境的内核版本完全一致。
4.3 rtl8125 加载后网卡灯不亮
现象:insmod r8125.ko成功,dmesg里也能看到驱动注册信息,但网口指示灯不亮,ip link显示NO-CARRIER。
原因:rtl8125 的固件文件没有正确加载,或者 ASPM 配置和主板冲突。麒麟 V10 默认的rtl_nic固件目录可能缺少 rtl8125 对应的固件文件。
解决:先确认固件是否加载成功:
dmesg | grep r8125 # 如果出现 "Failed to load firmware" 说明固件缺失从源码包的firmware目录拷贝固件到/lib/firmware/rtl_nic/,然后重新加载模块。如果固件正常但灯还是不亮,尝试关闭 ASPM:
sudo modprobe -r r8125 sudo modprobe r8125 aspm=04.4 网卡识别为 eth1 而不是 eth0
现象:新驱动加载后,网卡接口名变成了eth1或enp3s0,原来的eth0不见了,导致网络配置脚本失效。
原因:麒麟 V10 默认启用了 Predictable Network Interface Names,接口名由 PCI 位置决定,不是固定的eth0。另外,如果系统里同时存在 e1000e 和 rtl8125 两块网卡,加载顺序会影响命名。
解决:要么修改网络配置脚本适配新接口名,要么在内核启动参数里加net.ifnames=0禁用可预测命名:
sudo vi /etc/default/grub # 在 GRUB_CMDLINE_LINUX 里追加 net.ifnames=0 sudo grub2-mkconfig -o /boot/grub2/grub.cfg sudo reboot重启后接口名恢复为eth0、eth1的传统命名。
4.5 编译通过但 ethtool 看不到链路状态
现象:ethtool eth0输出里Link detected: no,但网线插着,交换机端口也是亮的。
原因:e1000e 驱动对某些 Intel 网卡型号的 PHY 初始化需要额外的模块参数,默认配置下可能没有正确协商速率。
解决:加载模块时指定速率和双工模式:
sudo modprobe -r e1000e sudo modprobe e1000e Speed=1000 Duplex=full如果还是不行,检查交换机端口是否强制了固定速率,和网卡自协商不匹配。常见做法是把交换机端口也设为自协商,或者两边都强制 1000M 全双工。
5. 进阶技巧:用 DKMS 管理驱动版本,避免内核升级后失效
手动编译的驱动最大的问题是内核一升级就失效,每次都要重新make一遍。DKMS(Dynamic Kernel Module Support)可以把驱动源码注册到系统里,内核更新时自动重新编译。麒麟 V10 的软件源里通常有 dkms 包,没有的话可以从 ISO 镜像里找。
5.1 为 e1000e 和 rtl8125 编写 dkms.conf
在源码目录下创建dkms.conf:
# e1000e 的 dkms.conf PACKAGE_NAME="e1000e" PACKAGE_VERSION="3.8.4" BUILT_MODULE_NAME[0]="e1000e" DEST_MODULE_LOCATION[0]="/kernel/drivers/net/ethernet/intel/e1000e" AUTOINSTALL="yes"# rtl8125 的 dkms.conf PACKAGE_NAME="r8125" PACKAGE_VERSION="9.007.01" BUILT_MODULE_NAME[0]="r8125" DEST_MODULE_LOCATION[0]="/kernel/drivers/net/ethernet/realtek" AUTOINSTALL="yes"参数说明:
PACKAGE_VERSION要和源码里的版本号一致,不能随便写。DEST_MODULE_LOCATION是模块安装到/lib/modules/$(uname -r)/下的相对路径,写错会导致dkms install失败。AUTOINSTALL="yes"表示内核更新时自动重新编译。
5.2 注册并安装到 DKMS
把源码拷贝到/usr/src/下,目录名格式为包名-版本号:
sudo cp -r e1000e-3.8.4 /usr/src/ sudo cp -r rtl8125-9.007.01 /usr/src/ sudo dkms add -m e1000e -v 3.8.4 sudo dkms add -m r8125 -v 9.007.01 sudo dkms build -m e1000e -v 3.8.4 sudo dkms install -m e1000e -v 3.8.4安装完成后用dkms status查看状态,应该显示installed。之后每次内核升级,DKMS 会自动触发重新编译,不需要手动干预。
5.3 验证 DKMS 是否生效
模拟内核升级测试比较麻烦,但可以手动触发一次重建:
sudo dkms remove -m e1000e -v 3.8.4 --all sudo dkms install -m e1000e -v 3.8.4如果重建过程中报错,查看/var/lib/dkms/e1000e/3.8.4/build/make.log,里面会记录完整的编译输出。常见问题是内核头文件路径变了,或者源码里的kcompat.h对新内核版本判断有误,需要手动打补丁。
从那以后我每次给麒麟 V10 装网卡驱动,都强制走一遍 DKMS 注册流程,哪怕当时只在一台机器上用。因为国产化现场的内核升级往往不是你能控制的,今天手动编译能跑,明天系统一更新就全白干。希望帮到你。
本文还有配套的精品资源,点击获取