ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

r8168驱动编译安装与dkms管理:解决Linux千兆网卡掉线问题

r8168驱动编译安装与dkms管理:解决Linux千兆网卡掉线问题 简介面向 CentOS 7 系统运维人员和刚开始接触 Linux 的读者这份驱动资源包主要应对瑞昱以太网卡在系统默认启用 r8169 驱动后出现的网络接口无法识别、传输速率不稳定、网卡模块加载失败等实际问题资料围绕内核 3.10 和 gcc12 编译环境提供 r8168 驱动替换方案既适合正式环境修复网卡故障也适合通过完整演练来熟悉驱动源码的编译与装载流程。资源包含四十个文件整体约一点三七兆字节核心是一个 HTML 图文教程页面同时搭配了十五张 PNG 操作截图、两张 JPG 演示图片、两张 GIF 动态示意图以及六个 JavaScript 和四个 CSS 文件用于还原教程页面的样式与交互整套内容按网页形态保存离线时也能直接打开浏览。目前已有二百七十二人学习下载。教程按照解压源码包、配置编译环境、编译驱动模块、安装模块并执行 modprobe r8168 加载的顺序展开加载完成后可用 ifconfig 或 ip addr 检查网络接口是否正常针对内核版本与驱动不匹配、必要依赖未安装、编译报错以及模块加载失败等状况资料也整理了实用的排查方法和原因分析能够帮助读者减少试错最终在 CentOS 7 上稳定启用 r8168 网卡驱动。1. r8168-8.048.03.tar.gz一个让千兆网卡不再掉线的驱动源码包如果你刚给一台老机器装上 Linux发现ip addr里只有 lo或者网络用着用着就断流十有八九是网卡驱动在作怪。r8168-8.048.03.tar.gz是 Realtek 官方为 RTL8111/8168/8169 系列千兆网卡发布的 Linux 驱动源码包很多主板自带的千兆网口用的就是这颗芯片。装 Linux 后默认走的是内核自带的r8169驱动它功能全但稳定性一直被人诟病尤其在新内核上偶发掉线、唤醒后失联、速度跑不满——换用 Realtek 官方这个r8168驱动是圈子里最常见、也最直接的解法。这篇笔记不聊泛泛的驱动原理直接按「确认硬件 → 手动编译 → dkms 接管 → 排坑 → 验证调优」的顺序走一遍。新手能照命令抄熟手可以直接跳到第 5 章看翻车记录。2. 装之前先认清网卡确认型号、内核版本与编译环境2.1 用 lspci 确认是不是 RTL8168/8111 芯片很多人在网上搜 r8168下回来一编译就报错最后发现网卡根本不是 Realtek 的——白忙活一场。第一步一定是确认网卡硬件命令很简单lspci | grep -i ethernet输出里找Ethernet controller:这一行。如果是Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller那恭喜你芯片对上了。如果显示的是 Intel、Broadcom 或者其他牌子这个驱动包跟你没关系别强行装。还有一个容易踩的坑lspci显示RTL8168但系统里已经加载了r8169内核模块。这在 Linux 上是常态——r8169是内核自带的通用驱动兼容一大票 Realtek 网卡包括RTL8168。所以先看当前加载哪个模块lsmod | grep r816如果输出既有r8169又在后面备注了(r8168?)别急这只是说明目前系统在用r8169。我们的目标就是把r8169停掉换成r8168。2.2 编译环境三件套gcc、make、内核头文件源码包要编译缺了编译环境就是第一步卡死。Debian/Ubuntu 系和 RHEL/CentOS/Fedora 系安装命令不一样# Debian/Ubuntu sudo apt install build-essential linux-headers-$(uname -r) dkms # RHEL/CentOS sudo yum install gcc make kernel-devel-$(uname -r) dkms装完之后做一次自检确保三个东西都在which gcc make ls -d /lib/modules/$(uname -r)/build如果第二个ls -d提示目录不存在说明内核头文件没装对版本。注意我这里的$(uname -r)是动态取当前内核版本号别手改成别的版本否则后面编译必报 unable to find kernel headers。这个命令在 Ubuntu 尤其常见apt 源里没有对应版本的 linux-headers 就会失效需要先sudo apt update再试。另外要强调一点确定内核版本时有个冷知识——某些云服务器的内核是定制过的$(uname -r)拿到的字符串在 apt/yum 源里根本找不到对应的 headers 包。这时候直接用发行版默认内核启动后重装一次别在定制内核上死磕。2.3 为什么默认的 r8169 驱动会让你翻车内核自带的r8169维护频率很高但这恰恰是问题来源。它对 RTL8168 这种老芯片的支持属于「兼容但不专注」社区里反馈最多的三个问题握手速率不稳定导致掉线、接收大流量时断流、休眠唤醒后网卡失联。我自己遇到过一台 Ubuntu 22.04 的机器r8169下 iperf3 跑到 700Mbps 就断流换成r8168后稳定跑满 940Mbps。Realtek 官方这个r8168驱动包其实是一套独立的源码不完全依赖内核里的通用框架它自己实现 NAPI 收包逻辑和中断处理行为更贴近固件期望。代价是每次内核大版本升级都可能要重新编译。所以正确姿势是先用命令手动编译装一遍验证芯片没问题再交给 dkms 管理第 4 章会细说。提示如果你的网卡是 RTL8125 这种 2.5G 型号r8168 这个包不支持要去 Realtek 官网找 r8125 的驱动。查型号用lspci -vnn | grep 10ec输出里10ec:8168对应千兆10ec:8125对应 2.5G。3. 手动编译安装 r8168 驱动从解压到 modprobe 的完整命令链3.1 解压并确认源码结构tar -xzf r8168-8.048.03.tar.gz cd r8168-8.048.03 ls -la源码包解开后目录里至少会有Makefile、src/子目录和一份READMEsrc/里面才是真正的驱动源码。8.048.03这个版本号需要单独说一句它不是越新越好我遇到过 8.050 以上版本在某些 RTL8168 老芯片上反而丢包如果你手里网卡是 2015 年之前的主板板载这个版本是一个很稳的选择。不要手贱去官网下最新版稳定优先。README 里会有支持的内核版本范围说明读一下src/Makefile也能看到TARGET变量——它定义了编译出来的内核模块文件名一般就是r8168.ko。这一步不用改任何东西只是确认目录完整。3.2 编译前的两个必要检查# 检查当前内核是否有 r8169 模块 ls /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/realtek/ # 检查内核是否开启了 CONFIG_R8169可忽略但要知道 grep CONFIG_R8169 /boot/config-$(uname -r) || true第一个检查很重要因为装完驱动后要把r8169拉黑如果不清楚它现在的位置拉黑容易漏。Debian/Ubuntu 上这个文件路径一般就是realtek/r8169.ko但有些发行版放在了别的子目录里。如果你用的是 secure boot 开启的 UEFI 机器还要检查mokutil --sb-state # 输出 SecureBoot enabled 的话模块签名是个问题Secure Boot 开启时未签名的第三方内核模块会被拒绝加载insmod会报permission denied或者module verification failed。常见做法是在 BIOS 里关掉 Secure Boot或者用发行版自带的mokutil --import导入自己的签名。这个看发行版文档就行这里不展开。对大多数个人 PC直接进 BIOS 关掉最省事。3.3 编译安装并加载驱动# 在 r8168-8.048.03 根目录下 sudo make clean sudo make modulesmake modules编译驱动它会生成src/r8168.ko。如果编译中间报错先看是不是缺头文件——第 2 章的三件套检查没通过的回来补装。编译成功后的安装sudo make install sudo depmod -a sudo modprobe r8168make install会把r8168.ko拷贝到/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/realtek/目录。depmod -a是重建模块依赖关系不执行的话后面modprobe可能说 module not found。modprobe r8168才是真正加载驱动它依赖depmod生成的 modules.dep 文件所以顺序不能反。加载之后立刻看状态lsmod | grep r816 ip addr showlsmod如果出现r8168并且网卡有了 IPDHCP 或静态配置说明驱动已经生效。但这里大概率你会看到r8169还在因为它和r8168都声称支持这款网卡内核按加载顺序决定谁绑定硬件。所以还要做下一步。3.4 黑名单 r8169 并确保开机自启sudo sh -c echo blacklist r8169 /etc/modprobe.d/blacklist-r8169.conf sudo update-initramfs -u sudo reboot把r8169拉黑后更新 initramfs重启之后系统就不会自动加载那个内核自带的驱动了。注意如果你只重启不更新 initramfsr8169可能在早期启动阶段就被加载r8168排不上队结果又是r8169接管网卡。重启后验证lsmod | grep r8168 ethtool -i eth0 # 把 eth0 换成你实际网卡名ethtool -i的输出里driver: r8168就对了。有些发行版网卡名是enp3s0或ens5别认死eth0用ip addr先看名字。这里有个细节值得说明blacklist r8169写进 modprobe.d 只是阻止自动加载如果后续用了 dkms 或者其他方式手动modprobe r8169它还是会加载。所以严格来说写上黑名单是「防自动加载」不是「彻底禁用」。要彻底禁用得把它从内核镜像里移除一般没必要不折腾。4. 用 dkms 接管驱动解决内核升级后网卡失联4.1 dkms 是什么为什么必须用它手动编译安装的驱动和内核强绑定。内核从 5.15 升到 6.1/lib/modules/$(uname -r)目录整个变了你之前编译的r8168.ko留在旧目录里新内核根本找不到。结果是系统启动后网卡又回到r8169或直接失联。DKMSDynamic Kernel Module Support就是为了解决这个问题它把驱动源码登记在/usr/src/下每次内核变更时自动重新编译并安装对应模块。装好 dkms 后就不用每次升级内核后手动折腾一遍编译的命令了。4.2 把 r8168 注册进 dkms 的核心命令sudo dkms add -m r8168 -v 8.048.03 sudo dkms build -m r8168 -v 8.048.03 sudo dkms install -m r8168 -v 8.048.03三条命令分别是登记、编译、安装。执行dkms add之前确认源码目录的顶层名字是r8168-8.048.03而不是别的因为 dkms 通过-m指定模块名、-v指定版本号去/usr/src/下找对应目录找不到就报错。dkms build比较吃时间输出日志里如果看到DKMS: Build Completed就过了。它实际做的事情和手动make modules一致只是把编译产物放到了 dkms 管理的目录里然后dkms install再链接到当前内核的 modules 目录。4.3 不同发行版的 dkms 差异处理Debian/Ubuntu 系装 dkms 后dkms add一般一次成功RHEL/CentOS 系需要注意 SELinux 上下文dkms install后模块文件可能被 SELinux 挡了加载表现就是modprobe r8168报权限错误但 dkms 日志显示安装成功。处理办法是临时让 SELinux 放行或者干脆给/usr/src/r8168-8.048.03打上正确的 SELinux 标签sudo restorecon -Rv /usr/src/r8168-8.048.03 /lib/modules/$(uname -r)/extraOpenSUSE 系则多一个weak-updates机制dkms 装完还要手动mkinitrd一次不然进入系统后内核根本没加载这个模块。这个问题在论坛上问得很多几乎都是这个原因。dkms status命令可以随时查看驱动在各内核下的编译状态dkms status r8168/8.048.03, 5.15.0-91-generic, x86_64: installed如果看到built但没installed说明编译过但没装进去手动执行sudo dkms install -m r8168 -v 8.048.03即可。要是看到failed直接去/var/lib/dkms/r8168/8.048.03/build/make.log看编译日志。4.4 有没有必要保留手动编译的模块用 dkms 之后手动编译装的那个r8168.ko可以留着但要注意优先级。dkms 管理的模块放在/lib/modules/$(uname -r)/updates/或extra/默认优先于kernel/目录下的同名模块。如果手动编译的也装了有可能出现两个r8168.ko内核模块加载机制一般会用后装的那个造成版本混乱。我的习惯是上了 dkms 就把手动的删掉sudo rm -f /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/realtek/r8168.ko sudo depmod -a删之前先确认路径别把别的模块删了。用 dkms 管理最大的好处是内核升级后不用管它自己会编译新内核的模块。代价是系统启动时会多花几秒跑 dkms 的编译流程但这点时间换一个稳定网卡很划算。5. r8168 驱动避坑记录掉线、编译失败与性能异常的排查写到这里全是实操里见过的真实问题。按「现象 → 原因 → 解决」写每一条都能对应具体命令。5.1 现象make 报错 unable to find kernel headers源码编译第一步就失败提示找不到内核头文件。新手容易狂装linux-headers-generic结果还是不行。原因是linux-headers-$(uname -r)的版本和你当前运行的内核不一致——常见于系统升级后没重启或者 apt 源里没有匹配版本。解决uname -r # 先确认当前内核版本 sudo apt install linux-headers-$(uname -r) ls -d /lib/modules/$(uname -r)/build # 确认存在如果apt install提示找不到包说明你的内核是定制版或所在源里没有换回发行版默认内核是大概率解法。我遇到一次 Ubuntu 的 HWE 内核源里没匹配头文件直接装 generic 重启后编译秒过。5.2 现象modprobe r8168 后网卡不生效lsmod 里根本没有它modprobe r8168不报错但lsmod看不到网卡也没被绑定。原因多半是r8169已经硬绑定了 PCI 设备modprobe加载 r8168 时它尝试注册同一个 PCI ID被内核拒绝了。解决确认当前有没有r8169先把它卸了再载入 r8168sudo modprobe -r r8169 sudo modprobe r8168如果modprobe -r r8169提示被占用先ip link set 网卡名 down再卸载。这种问题很容易在调试时误判成驱动没装对其实顺序问题。5.3 现象网速永远跑不满千兆iperf3 只有 400Mbps驱动加载了链路也显示 1000Mbps但速度上不去。先排除网线、对端设备问题然后查中断处理ethtool -S 网卡名 | grep -E tx|rx | head -20 cat /proc/interrupts | grep r8168r8168驱动默认不一定开启多队列/proc/interrupts里如果只有一个中断号对应网卡说明单队列模式大流量时单 CPU 软中断跑满就掉速。ethtool -L 网卡名 combined 4能把队列数调到 4前提是芯片和驱动支持。RTL8168 有些版本只支持单队列调不动就认命千兆跑 700-800Mbps 是常态不是 bug。5.4 现象休眠唤醒后 ping 不通这个坑在笔记本上尤其常见。合盖再打开网卡 link 灯亮着但 ping 不通必须重启网络或强制 down/up 一次才能恢复sudo ip link set 网卡名 down sudo ip link set 网卡名 up根本原因是r8168在休眠时没正确恢复 PCI 设备的 DMA 状态老版本驱动尤其明显。解决思路是避免休眠唤醒或者用ethtool -s 网卡名 wol d把 WoL 相关触发关掉试试。我实测 8.048.03 这个版本在笔记本上还是偶发但比r8169好很多。要彻底根治只能升级驱动版本或换内核没有一劳永逸的配置。5.5 现象内核升级后 dkms 没自动编译网卡又失联装了 dkms 但升级后网卡还是不行先查dkms status。大概率是 dkms 注册时用的源码目录在/usr/src/r8168-8.048.03删掉了或者被搞坏。另一个隐蔽原因dkms build在新内核下因为 GCC 版本变化失败比如 GCC 12 对老内核模块的某些隐式声明变严格。/var/lib/dkms/r8168/8.048.03/build/make.log里如果看到error: implicit declaration of function说明源码和编译器不匹配。解决方案是给 make 加参数放宽警告为不致命错误但更稳的是换一个更新版的驱动源码包重新 dkms add。5.6 现象装完 r8168 后发现 VFIO 直通或虚拟机网络异常如果你这机器上有 PCIe 直通需求装了官方驱动后iommu_group对网卡的分组没有变化但部分虚拟化环境里r8168的 NAPI 轮询和多队列行为会跟 vhost-net 冲突表现为虚拟机吞吐量暴降。解决办法虚拟机场景用默认virtio-net配半虚拟化网卡别把物理网卡直通过去。物理机用 r8168 没任何问题PVE/ESXi 里遇到宿主机网卡断流倒是可以试试关闭网卡的 TSO/GROethtool -K 网卡名 tso off gso off gro off这算是个偏门经验但几乎没在任何文档里看到记录在这里。6. 验证与进阶用 ethtool、iperf3 和日志确认驱动真实生效6.1 三分钟功能验证清单安装和避坑之后落地上线前建议按这个顺序验一遍ethtool -i 网卡名 # 确认 driver: r8168 ethtool 网卡名 # 看 Speed: 1000Mb/s, Duplex: Full ip addr show 网卡名 # 确认 IP 正常 ping -c 5 网关IP # 连通性 iperf3 -c 对端IP # 测吞吐千兆环境应 900Mbpsethtool -i的driver字段是最重要的Speed如果显示 100Mb/s先看是不是网线或对端交换机端口问题驱动本身一般不会把链路速率降下来。6.2 进阶调优中断合并与队列参数r8168支持通过ethtool -C调中断合并参数。在高 PPS 小包场景把rx-usecs调低能降低延迟但会增加 CPU 中断开销ethtool -C 网卡名 rx-usecs 1 tx-usecs 1这是典型的延迟优化方向适合游戏服务器或高频交易场景。反过来如果是大流量传输场景调高到 100 以上更省 CPU延迟高一点无所谓。还有一个很多人忽略的参数r8168模块参数tx_ring和rx_ring控制环形队列大小。默认是 1024可以加载时指定sudo modprobe r8168 tx_ring2048 rx_ring2048但注意这是模块级参数dkms 接管后要用options文件持久化写在/etc/modprobe.d/r8168.conf里。tx_ring改大在高速小包场景对吞吐有正向帮助但也吃内存2048 是极限别乱往上加。最后说一个我自己的习惯每换一个内核或驱动版本我会同时对/var/log/kern.log和dmesg做一次grep r8168看看有没有NETDEV WATCHDOG这类软超时警告。如果驱动在 60 秒内没收到中断内核会报这个这是网卡失联的前兆提前看到了能少一次线上事故。把驱动从「能通」到「稳」这个过程靠的就是这类细节——版本不要乱追新队列和中断参数按场景调升级用 dkms 兜底剩下的交给时间验证。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进