简介:面向银河麒麟V10系统维护者与网卡驱动开发者的可编译网卡驱动资源包,解决e1000e与RTL8125两款网卡在国产操作系统上因内核适配导致的编译失败问题。包内已提前处理重复定义删除、函数参数修改等兼容性调整,可直接用于编译安装。资源共56个文件,以C源码、头文件为主,辅以Makefile构建脚本、README说明及ethtool工具源码,适配性改动清晰可见,便于二次排查。压缩包整体约483KB,小巧完整,适合系统集成、信创环境部署及驱动开发学习场景。目前已有2735人学习下载,对快速验证麒麟V10网络功能具有实用参考价值。
1. 银河麒麟V10能编译通过的 e1000e 和 rtl8125:先看懂卡点再动手
一台刚装好的银河麒麟 V10,开机后ip link里只有 lo,板载 Intel I219 和 Realtek RTL8125 都“失踪”了。很多人第一反应是去网卡官网拉驱动,结果make还没跑完就死在include/linux/compiler_types.h。这个报错和驱动本身关系不大,卡点在四件事:kernel-devel 版本对不对、gcc 和内核是不是同一套、r8169 有没有抢占设备、Secure Boot 有没有拦模块。这篇按“先查环境、再编 e1000e、再编 rtl8125、最后处理报错”的顺序走,不绕弯,适合做网卡驱动替换的运维和集成商直接照着敲。
2. 编译前先摸环境:内核版本、gcc 和 kernel-devel 一个都不能少
编译驱动本质上是把.c文件对着当前内核的build目录生成.ko。银河麒麟 V10 是个大版本号,下面的桌面版、服务器版、SP1/SP2/SP3 各自内核不一样,驱动源码只在匹配的uname -r下才能一次通过。所以动手第一步不是解压源码,而是把编译环境摸清楚。
2.1 是 4.19 还是 5.4?先查 uname -r 再决定编译路线
uname -r cat /etc/kylin-release lscpu | grep Architectureuname -r输出形如4.19.90-23.8.v2101或5.4.18-35.2-generic,这个字符串决定了后面要装的 kernel-devel 版本,也决定了驱动源码能不能直接编译。银河麒麟 V10 桌面版常见内核是 4.19,服务器 SP 版本里出现过 5.4,不同小版本之间如果只看“V10”就去下载驱动,十次有八次会踩到 API 差异。
4.19 和 5.4 在 netdev 这一层的差别挺大,比如ndo_set_features、vlan相关函数、phydev结构体成员都有改动。老的 r8125 驱动代码在 5.4 上编译会报implicit declaration of function,这不是代码烂,是内核把接口换了。看到uname -r之后,e1000e 走“内核自带源码目录编译”路线,rtl8125 走“外部模块编译”路线,这个分工在后面会反复用到。
2.2 无网环境怎么把 gcc、make、kernel-devel 一次抓齐
银河麒麟 V10 很多实施现场是内网,机器上连yum仓库都没配。没有 gcc 和 kernel-devel,后面所有步骤全废。常见做法是在一台能联网的同架构、同大版本机器上把依赖包抓下来,再拷进去。
# 能联网的同一架构 Kylin V10 机器上执行 mkdir -p /tmp/kylin-drv sudo yum install --downloadonly --downloaddir=/tmp/kylin-drv \ gcc make kernel-devel kernel-headers elfutils-libelf-devel tar czf kylin-drv.tar.gz -C /tmp/kylin-drv .把kylin-drv.tar.gz传到目标机器后:
tar xzf kylin-drv.tar.gz -C /tmp/ sudo rpm -Uvh /tmp/kylin-drv/*.rpm注意两点。第一,抓包机器的系统版本和架构必须和目标机一致,x86_64 的包装不到 arm64 上。第二,kernel-devel后面要拼uname -r,如果你直接yum install kernel-devel,仓库会默认装“最新”的内核头文件,装完大概率跟当前内核不匹配。正确做法是显式指定:
sudo yum install -y kernel-devel-$(uname -r)如果桌面版用的是 dpkg 系,逻辑一样,把命令换成apt-get download linux-headers-$(uname -r)再dpkg -i。另外 Kylin 的安装 ISO 里通常有kernel-devel的 rpm,挂载后find /media -iname '*kernel-devel*'也能直接找到,离线环境下这条路往往更快。
2.3 用三行命令验证编译环境,别等 make 报错才回头
ls -ld /lib/modules/$(uname -r)/build grep -E 'CONFIG_MODULES|CONFIG_MODULE_SIG' /lib/modules/$(uname -r)/config ls -l /usr/src/kernels/$(uname -r)/scripts/mod/modpost gcc --version第一条看/lib/modules/$(uname -r)/build是不是一个能用的软链。软链跑到/usr/src/kernels/4.19.90-...,而这个目录不存在,就是 kernel-devel 没装全。第二条确认内核把模块加载功能打开了;如果CONFIG_MODULE_SIG是y,后面还要留意签名问题。第三条最关键,modpost是生成.ko的最后一道工具,它不存在说明/usr/src/kernels下只有残缺的头文件,直接把下一步make喂进去照样报 “No rule to make target”。
如果以上检查都过了,但/usr/src/kernels/$(uname -r)/下面没有.config,补一步:
cd /usr/src/kernels/$(uname -r) cp /lib/modules/$(uname -r)/config .config make modules_prepare这一步会把scripts、Module.symvers、include/generated等编译外部模块要用的中间文件生成出来。很多“能编译通过的驱动”在别的机器上换个环境就失败,差的就是这一步没做。
3. 编译 e1000e:Intel 千兆网卡驱动在麒麟 V10 上的落地步骤
e1000e 是 Intel 官方给 82571 到 I219 系列千兆网卡的驱动,Linux 内核树里本身就带着一份。银河麒麟 V10 上最常见的坑不是“驱动不存在”,而是系统里那份 e1000e 太老、没有覆盖新网卡 PCI ID,或者模块已经加载但固件缺失导致接口起不来。编译前先判断到底缺哪一环。
3.1 先判断要不要升级 e1000e:内核自带版本和网卡型号对上再说
lspci -nn | grep -i ethernet modinfo e1000e | grep -E 'filename|alias|version' ip -br linklspci -nn会给出类似8086:15b8的厂商号和设备号,这是判断内核驱动是否支持的最硬指标。拿这个设备号去和modinfo e1000e输出的 alias 列表对,能对上,说明内核已经认识这块卡,没必要满世界找新驱动;对不上,才需要编译新版 e1000e。
还有一个很容易误判的点:银河麒麟 V10 默认启用enp0s31f6这类可预测接口名,网卡不是“消失”了,只是不叫eth0。先ip -br link看一眼,别一上来就make。如果接口在但没地址,那是 NetworkManager 或固件问题,跟驱动编译无关。
如果dmesg里有Failed to load firmware,e1000e 系列网卡还要检查/lib/firmware/e1000e/下有没有对应.bin。银河麒麟 V10 的linux-firmware包偶尔缺新款网卡的固件,单独把固件文件补齐比重编驱动省事。
3.2 在麒麟 V10 上编译并替换 e1000e 的最小命令
有完整内核源码树时,推荐直接编内核树里的 e1000e,这样 vermagic 一定对得上:
cd /usr/src/kernels/$(uname -r) cp /lib/modules/$(uname -r)/config .config make modules_prepare make M=drivers/net/ethernet/intel/e1000e sudo cp drivers/net/ethernet/intel/e1000e/e1000e.ko /lib/modules/$(uname -r)/updates/ sudo depmod -amake M=drivers/net/ethernet/intel/e1000e的意思是只编这一个子目录,不碰整个内核。modules_prepare已经在第 2.3 节跑过的话,这里可以直接跳到make M=。编译正常的话,最后会看到Building modules, stage 2.和MODPOST一行,说明 modpost 成功,生成的.ko是有效的。
把e1000e.ko拷到/lib/modules/$(uname -r)/updates/是常见做法,这个目录优先级高于内核自带的强依赖路径,depmod -a之后modprobe e1000e会优先加载这一份。
如果你拿到的是 Intel 放出的独立 e1000e 源码包(解压后目录里有个src),流程同样简单:
tar zxf e1000e-*.tar.gz cd e1000e-*/ cd src make clean make sudo make install sudo depmod -a独立包里的 Makefile 会自动读取/lib/modules/$(uname -r)/build,所以前面环境检查里的软链是否有效,直接决定这一步成不成功。装完后先卸载旧模块再加载新的:
sudo modprobe -r e1000e 2>/dev/null sudo modprobe e1000e ip -br link3.3 e1000e 的三个参数:InterruptThrottleRate、TxIntDelay、RxIntDelay
e1000e 编译通过只是第一步,加载参数不合理,跑业务时 CPU 会莫名其妙被软中断吃满。三个最常调的参数写进/etc/modprobe.d/e1000e.conf:
sudo tee /etc/modprobe.d/e1000e.conf <<'EOF' options e1000e InterruptThrottleRate=3,3,3,3 TxIntDelay=64 RxIntDelay=64 EOFInterruptThrottleRate控制每秒钟最多产生多少中断,0表示关闭节流,追求最低延迟;3是自适应模式,适合大多数业务。如果你的机器是拿来做 NAS 或软路由,想降 CPU 占用,可以把它设成一个固定值,比如 4000,代价是单包延迟会高一点。TxIntDelay和RxIntDelay控制发送/接收中断的延迟,默认 64 对千兆场景基本够用,不要为了“压榨性能”调到 0,小包场景反而会把 CPU 打满。
加载完用下面命令确认参数真的生效:
cat /sys/module/e1000e/parameters/InterruptThrottleRate ethtool -i enp0s31f6ethtool -i看到的driver: e1000e和version能证明当前跑的是不是新编出来的模块。如果这里显示的版本还是内核自带的老版本,大概率是depmod没执行,或者/lib/modules/$(uname -r)/updates/里的文件权限不对。
4. 编译 rtl8125:Realtek 2.5G 网卡的选型和手把手编译流程
RTL8125 是 Realtek 2.5G 网卡,银河麒麟 V10 服务器上很常见。它比 e1000e 麻烦在“驱动家族太乱”,下载一个不对版的源码,编译报错能把人绕晕。这一章先把名字理清楚,再给可复现的编译命令。
4.1 先分清 r8169、r8125、rtl8125,避免下错包、装错模块
| 名字 | 模块名 | 适用场景 |
|---|---|---|
| r8169 | r8169.ko | 内核自带,覆盖部分 RTL8168/RTL8125,兼容性看内核版本 |
| r8168 | r8168.ko | Realtek 官方千兆驱动,主要是 RTL8168 系列 |
| r8125 | r8125.ko | Realtek 官方 2.5G 驱动,目标就是 RTL8125 |
| rtl8125 | 可能是 r8125.ko | 第三方包名混乱,最终看编译产物 |
标题里写的是rtl8125,但 Realtek 官方驱动包解压后目录名通常是r8125-版本号,模块名也是r8125。看到这个不一致不用慌,认模块名最可靠:编译产物是r8125.ko,就说明下对了。
动手前先看当前内核到底把这块 2.5G 网卡给了谁:
lspci -nn | grep -i ethernet lsmod | grep -E 'r8169|r8125' modinfo r8169 | grep -E 'filename|alias'如果lspci -nn显示10ec:8125,lsmod里挂着r8169,并不代表网卡能跑满 2.5G。内核自带的 r8169 对 RTL8125 的支持经常只停在“能识别、能 link”的层面,跑内网大流量时可能掉速或丢包。要发挥 2.5G,常规做法是编译 Realtek 官方 r8125,然后让 r8169 让位。
4.2 编译 r8125 的最小命令:make clean modules + make install
拿到r8125-*.tar.gz之后,进入源码目录直接编译:
tar zxf r8125-*.tar.gz cd r8125-*/ make clean modules sudo make install sudo depmod -amake clean modules是 Realtek 驱动包里常见的组合写法,先清理旧对象,再通过内核 build 系统生成模块。make install会把r8125.ko放到/lib/modules/$(uname -r)/updates/或类似目录,depmod -a刷新模块依赖。如果 make 过程提示找不到内核 build 目录,显式传参再跑一次:
make KSRC=/lib/modules/$(uname -r)/build modules编译成功后别急着modprobe r8125,先把旧驱动拿掉。r8169 如果已经占了这块网卡,r8125 可能加载也白加载。但在 SSH 连接的机器上执行rmmod r8169要非常小心,如果你是靠这块网卡连的机器,命令一执行连接就断了。建议走 KVM/物理控制台操作,或者写进启动加载流程后重启。确认操作的命令如下:
sudo rmmod r8169 2>/dev/null || true sudo modprobe r8125 ip -br link出现新的enp*接口后,用ethtool -i确认驱动名字是r8125,再用ethtool看协商速度:
ethtool -i enp3s0 ethtool enp3s0如果是Speed: 2500Mb/s,说明 r8125 真正接管了。如果还是1000Mb/s,检查网线、对端交换机端口和ethtool -s enp3s0 autoneg on是否开启。网卡参数没开对,编译再成功也只是“能加载”,不是“能跑满”。
4.3 用 DKMS 接管 r8125,内核升级后不用重新手工编
r8125 是外部模块,内核一升级,/lib/modules/新版本下面没有它,网卡就掉。银河麒麟 V10 如果后续打补丁升级内核,总不能每次手动编。用 DKMS 管理一次,之后新内核编译时会被自动带出来。
ver=$(basename "$PWD" | sed 's/^r8125-//') sudo rm -rf "/usr/src/r8125-$ver" sudo cp -a "$PWD" "/usr/src/r8125-$ver" sudo dkms add -m r8125 -v "$ver" sudo dkms build -m r8125 -v "$ver" sudo dkms install -m r8125 -v "$ver" sudo dkms status这段脚本假设源码目录名是r8125-9.xxx这种格式,basename取出目录名,sed去掉r8125-前缀,剩下的就是 DKMS 要的版本号。如果你的目录名是rtl8125-...,把sed里的前缀改成rtl8125-即可。执行dkms add之后,/usr/src/下就有了标准源码布局;dkms build如果不报错,说明这个驱动在当前内核上没问题;dkms install才真正生成并安装.ko。
注意一点:DKMS 本身也要装,离线环境里记得把dkms的包提前抓进第 2.2 节那批依赖里。另外 DKMS 编译依赖kernel-devel,如果新内核被装上但新内核的kernel-devel没装,DKMS 照样失败。检验方式是升完内核后看/var/lib/dkms/r8125/*/build/make.log,报错基本都指向头文件目录缺失。
5. 编译报错与避坑:银河麒麟 V10 上最常见的 4 个翻车现场
编译驱动报错现场千奇百怪,但银河麒麟 V10 上反复出现的就是下面几个。每个都按“现象 -> 原因 -> 解决”来写,遇到直接对号入座。
5.1 “include/linux/compiler_types.h”找不到:build 软链指向空目录
现象是 make 刚开始就死在这一行:
fatal error: include/linux/compiler_types.h: No such file or directory这行报错几乎可以断定/lib/modules/$(uname -r)/build是个坏软链,或者它的目标目录里只有 include 头文件、没有完整内核构造树。银河麒麟 V10 上最常见的情况是装了kernel-headers但没装kernel-devel,或者kernel-devel版本和当前内核不一致。
解决方法是先看软链接指向哪里:
ls -l /lib/modules/$(uname -r)/build rpm -qa | grep kernel-devel如果build指向的目录不存在,重新安装精确版本:
sudo yum install -y kernel-devel-$(uname -r)装完后再进/usr/src/kernels/$(uname -r)做一次make modules_prepare。缺头文件的问题比缺.c文件难诊断,因为 make 往往只报第一个被杀掉的头文件名字,实际缺的是整个include/generated目录。这个目录就是modules_prepare生成的。
5.2 “unrecognized command-line option ‘-fstack-protector-strong’”:gcc 和内核不是同一套
现象是编译时 gcc 突然报不认识-fstack-protector-strong参数,或者干脆报Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: -fstack-protector-strong not supported by compiler。
原因是内核在编译时开启了栈保护强模式,当前调用到的 gcc 太老,不支持这个参数。银河麒麟 V10 如果之前装过 devtoolset 或自定义工具链,PATH里可能混进了旧版本 gcc。还有一种情况是CC环境变量被设成了某个交叉编译器,make 不认。
先看内核是谁编的:
cat /proc/version gcc --version which gcc/proc/version里会写内核编译时用的 gcc 版本和命令行。让当前 gcc 主版本尽量和它对齐,最省事的做法是卸掉自定义工具链或清掉环境变量再编:
env -u CC make clean modules如果系统默认 gcc 确实太老,直接sudo yum install -y gcc装一个发行版配套版本,别自己拉最新的 gcc 12。内核 4.19 本身就是用它当时的工具链生成的,换个太新的编译器反而更容易触发-Werror一类问题。
5.3 “No rule to make target ‘modules’”:kernel-devel 装了一个但不匹配
现象是执行make modules或make M=...时,make 找不到目标,再往下看还有scripts/Makefile.build: No such file or directory。
原因是/lib/modules/$(uname -r)/build软链存在,但/usr/src/kernels/$(uname -r)下只有零散的Makefile和include,没有scripts,也没有.config。这通常是把kernel-headers当成kernel-devel装了,两者的内容结构差很多。
检查并修复:
ls /usr/src/kernels/$(uname -r)/scripts/Makefile.build sudo yum install -y kernel-devel-$(uname -r)装好后再回到源码目录执行:
cd /usr/src/kernels/$(uname -r) cp /lib/modules/$(uname -r)/config .config make modules_prepare这条命令会补出scripts、Module.symvers、include/generated等 make 要用的文件。注意不要在只装了kernel-headers的环境里强行编译,省那一次 rpm 安装,后面会浪费更多时间。
5.4 编译通过但网卡不亮:r8169 抢占、Secure Boot 和接口改名三连
现象是最痛苦的一种:make install全部成功,modprobe r8125也没报错,但ip link里就是没有新接口。查dmesg又看到module verification failed或者Link is down。
三个原因按概率排:第一,r8169 还抢着这块设备,r8125 虽然能插入内核,但设备已经被占,不会重复生成接口;第二,BIOS 开了 Secure Boot,内核 lockdown 拒绝加载未签名模块;第三,接口被 systemd 改名成enp3s0但没看到,或者 udev 规则把名字改飞了。
先处理 r8169 抢占。把 r8169 写进黑名单,重启时让 r8125 唯一接管:
echo "blacklist r8169" | sudo tee /etc/modprobe.d/blacklist-r8125.conf sudo dracut -f --kver $(uname -r) 2>/dev/null || sudo update-initramfs -u -k $(uname -r)再查 Secure Boot 状态:
mokutil --sb-state dmesg | grep -i 'module verification'如果确实开了 Secure Boot,要么进 BIOS 关掉,要么用内核自带的scripts/sign-file给.ko签名。签名涉及证书生成和 MOK 导入,比编译本身还麻烦,非必须不推荐。关闭 Secure Boot 后,重新modprobe r8125一般就能出现接口。
接口名的问题其实最常被冤枉。银河麒麟 V10 默认使用 systemd 的可预测命名,ip -br link看到的可能是enp3s0,不是eth0。想要固定成eth0,写一个.link文件:
[Match] MACAddress=xx:xx:xx:xx:xx:xx [Link] Name=eth0放到/etc/systemd/network/10-eth0.link,重启后生效。这个文件里的 MAC 地址要用ip link看到的实际值,别抄主板贴纸,很多时候贴纸和系统读到的不一致。
6. 收尾:把驱动写进 initramfs,重启和压测一遍才算完
6.1 dracut/mkinitrd 二选一,把 e1000e 和 r8125 预加载
驱动装好、depmod -a也跑了,但很多同事在重启后掉网,原因只有一个:模块没进 initramfs。银河麒麟 V10 的 initramfs 生成工具因系统版本而异,安全做法是两条都试,哪条认了用哪条:
sudo dracut -f /boot/initramfs-$(uname -r).img $(uname -r) 2>/dev/null \ || sudo update-initramfs -u -k $(uname -r)生成完之后确认一下模块真的被打进去了:
lsinitrd /boot/initramfs-$(uname -r).img 2>/dev/null | grep -E 'e1000e|r8125'如果你的系统盘是本地 SATA/NVMe,这个步骤省了也不见得马上出事;但只要涉及网卡启动、iSCSI 根盘或远程安装,这个步骤必做。我的习惯是无论本地盘还是网络盘都做一次,因为内核升级后 initramfs 重建是自动的,提前把驱动交给 DKMS 和 initramfs 管理,能少接很多半夜电话。
6.2 重启后的验证顺序:ethtool、dmesg、iperf3
重启后别急着说“搞定了”,按顺序验证:
ip -br link show ethtool -i enp3s0 ethtool enp3s0 dmesg -T | grep -E 'r8125|e1000e'ethtool enp3s0能看到Speed和Duplex;2.5G 网卡如果协商成 1000Mb/s,大概率是网线或对端端口的问题,不是驱动问题。驱动加载是否干净要看dmesg里有没有failed、timeout这类词。有tx timeout时继续查ethtool -S里的tx_timeout计数,这个计数不为 0 说明驱动和硬件之间有异常,可能是 PCIe 省电或中断参数没调对。
最后做一次长时压测,单次 ping 通不算数:
iperf3 -c 192.168.1.1 -t 60 -P 4跑完看四个流的聚合带宽。如果掉到 1G 以下,回到第 4.3 节检查 r8169 是否真的被黑名单拦住,或者第 3.3 节的中断参数设置。驱动编译通过只是拿到了入场券,真正交付给业务的是“重启后还在、高负载不丢、长时间不 hang”的模块。
我自己每次装完驱动的固定动作是:先modinfo r8125把vermagic记下来,重启后再对比一次;然后主动sudo reboot,绝不在不重启的状态下验收。这两步看起来多余,但能把“编译通过”和“能用”之间的差距一次性补齐。希望帮到你。
本文还有配套的精品资源,点击获取