资讯动态

海光网卡驱动安装实战:从内核适配到避坑排查

发布时间:2026/10/13 1:26:41 来源:尧图企业网站定制
简介成都海光网卡驱动安装包是一份面向系统管理员、运维工程师及嵌入式开发者的网卡驱动资源主要解决海光网卡在国产化服务器与主流操作系统下的识别、加载与调优问题。压缩包共22个文件约146KB包含14个C源码文件、3个头文件以及Makefile、mk、shell脚本和readme说明既具备驱动主体代码也附带编译配置与安装指引便于在目标环境中按需编译和部署。目前已有658人学习下载适合需要掌握驱动二次编译、排查网卡异常或进行国产平台适配的读者。通过阅读源码和构建脚本可以深入理解驱动的模块结构、编译依赖和加载流程同时也为后续维护高速网卡和调优网络性能提供了可参考的工程基础。安装前注意核对系统内核版本与网卡型号并通过可靠渠道获取配套工具以保证安全性。1. 成都海光网卡驱动安装包到底在解决什么问题一台刚装完系统的海光平台服务器ip link里死活看不到网口lspci却显示设备就在 PCIe 总线上——这是成都海光网卡驱动没加载时最典型的现象。服务器不是没有网卡而是内核根本不认识它自然也就不会创建 eth0/ensXXX 这样的网络接口。所谓成都海光网卡驱动安装包就是针对海光服务器板载网卡或配套网卡芯片提供的内核模块与安装脚本集合把「设备存在」变成「设备可用」。写这篇笔记的直接原因是很多同行在这件事上被折腾到怀疑人生装个驱动花了半天最后发现是内核版本、模块签名或者中断绑定哪一步出了问题。这篇文章面向的是负责服务器交付、Linux 环境运维、以及做国产化硬件适配的工程师目标是让新手照着步骤十分钟内把网卡点亮让熟手直接拿走避坑清单少走弯路。2. 驱动与内核的适配逻辑为什么网卡不是“装上就能用”2.1 网卡驱动在系统里到底扮演什么角色网卡驱动不是一个独立运行的程序而是一个加载进内核地址空间的模块通常以.ko文件存在。它做的事情是把内核的网络协议栈和具体的物理网卡硬件桥接起来收包时网卡把 DMA 写进内存的数据包交给驱动注册的poll回调发包时协议栈通过ndo_start_xmit接口把 skb 交给驱动驱动再通过寄存器或 DMA 描述符把数据推到网卡。当你说“安装网卡驱动”本质上是让内核在启动或运行时加载这个模块并且在 PCIe 设备的 vendor/device ID 与模块的modaliases表匹配时自动绑定设备。海光平台上的网卡控制器常见做法是集成在主板上的多端口千兆或万兆网卡有些型号芯片型号相对特殊发行版自带的通用驱动要么没有包含要么包含的版本过旧导致无法识别或者只有基础功能。这里要区分一个概念lspci能看到设备说明 BIOS 和 PCIe 枚举没有问题lspci -k显示kernel driver in use: (none)说明内核没有匹配到可用的驱动此时ip link必然空空如也。驱动安装包要解的问题就是建立「设备型号 → 内核模块 → 网络接口」这一整条链路。2.2 安装包的常见形态rpm、dkms 与 tar 源码包厂商提供的驱动安装包一般有三种打包方式选哪个不完全是偏好问题更多取决于系统发行版和后续维护方式。用一个表格来看清区别安装包形态典型包名特征升级内核后行为适合场景kmod 类 rpm 包包名带kmod-前缀需要重新安装或等待新版包RHEL/CentOS 系不想自己编译dkms 源码包内部带 dkms.conf自动针对新内核重建模块需要频繁升级内核的环境tar 源码包目录里有 Makefile需要手动重新 make非主流发行版或定制内核RHEL 系系统上最常见的是 kmod 风格的 rpm 包装完后模块文件被放到/lib/modules/$(uname -r)/extra/目录然后运行depmod刷新模块依赖再modprobe加载。这种方式的好处是模块生命周期由 rpm 数据库管理卸载干净不会留下半编译的中间文件。dkms 方式我更喜欢用在工作站或测试机上。它把模块源码注册到 dkms 框架里每次内核更新dkms 会自动触发重建不需要人工介入。缺点是对编译链有依赖gcc、make、kernel-devel缺一不可而且如果系统里同时装了多个内核版本dkms 会为每个版本各编一次耗时按版本数翻倍。2.3 内核版本和编译链两个看不见的“紧箍咒”内核模块不是独立可执行文件它必须与当前运行的内核在 ABI 上保持一致。内核为了锁定模块的兼容性编译时会在模块的.modinfo段里写入vermagic字段包含内核版本号、SMP 支持、PREEMPT 选项等。强行用insmod加载一个版本不匹配的模块内核会直接报Invalid module format这些是模块加载失败的常见原因。因此驱动安装包对系统有一个硬性要求模块是针对哪个内核版本编译的就必须加载到哪个版本上。源码包方式安装前至少要确认三件事uname -r的内核版本、/lib/modules/$(uname -r)/build是否存在、gcc --version与编译当前内核的编译器是否兼容。这三件事不查清后面编译过程大概率会翻车而且报错信息往往不是直接说“版本不对”而是某个头文件找不到或语法错误容易让人误判成代码问题。2.4 自带驱动与厂商驱动的取舍有些海光网卡在较新内核里能被igb、i40e这种通用驱动识别但功能上打了折扣。常见的缺功能表现是多队列只有默认的 2~4 个、RSS 哈希不可调、ethtool -L组合通道失败。这种情况下要不要换装厂商驱动取决于你的业务网卡承载的流量模型。如果你的服务器只是跑管理网、SSH、日志传输内核自带驱动能认出来就直接用没必要折腾厂商驱动——自带驱动意味着已经进入内核维护树随系统升级不会被遗忘。但如果这台机器是跑存储前端、计算节点数据面或视频转码集群的南向流量多队列和中断亲和性直接影响吞吐和 CPU 开销就该认真装厂商提供的驱动并且手动调 RSS 队列数。3. 安装前三步确认网卡型号、内核版本与系统网络现状3.1 用 lspci 和 dmesg 确认网卡型号与驱动加载状态动手装驱动之前先把目标的身份确认清楚。lspci输出中的 vendor ID 与 device ID 是内核匹配驱动的核心依据厂商驱动安装包里的 modaliases 规则就是围绕这个 ID 写的。# 查看网卡设备及当前驱动占用情况 lspci -nnk | grep -i -A3 ethernet # 查询设备详细 ID lspci -nn | grep -i ethernet # 看启动日志里与网络设备相关的记录 dmesg | grep -i -E eth|net|pci | tail -50lspci -nnk中-nn显示数字形式的 vendor/device ID-k显示该设备当前使用的内核驱动。如果kernel driver in use是空的说明设备未被绑定如果显示的是另一个名字说明通用驱动抢占了需要考虑先 blacklist。dmesg里能看到设备被枚举时内核给的probe结果比如Direct firmware load failed这种提示往往意味着驱动框架在了但缺少固件文件。确认 vendor/device ID 之后把它记下来。在modprobe.d配置和模块加载日志里判断设备是否被正确匹配最后都要回到这个 ID 上来对照。3.2 检查内核版本与构建依赖避免编译期翻车源码包编译安装时90% 的失败发生在找不到内核头文件这一步。make过程中驱动源码要引用内核源码树里的linux/version.h、asm/types.h等文件而这些文件由kernel-devel包提供版本必须与uname -r严格一致。# 查看当前内核版本 uname -r # 检查内核头文件是否已安装 ls /lib/modules/$(uname -r)/build/Makefile # 检查 gcc 与 make 是否可用 gcc --version | head -1 make --version | head -1 # RHEL/CentOS 系安装匹配版本的 kernel-devel yum install -y kernel-devel-$(uname -r)如果/lib/modules/$(uname -r)/build目录不存在说明 kernel-devel 没有安装或版本不匹配。不要直接装了 kernel-devel 就走装完后再执行一次上面的ls确认Makefile文件真实存在。这个目录是一个软链接链到/usr/src/kernels/下对应的目录有时候包装了但链接断了编译仍然会失败。还有一个容易忽略的点gcc版本不能与编译当前内核的编译器差距过大。比如某系统内核在旧编译器下构建系统里却装了新版 gcc源码包里某些内联汇编写法在新编译器下报错这种情况不是驱动代码的 bug但你只能选择换编译器版本或者换驱动版本。3.3 备份现有网络配置防止驱动加载后接口命名跳跃很多人装了驱动重启后直接傻眼:接口名从eth0变成了ens2f0或者从eno1变成了eth1业务脚本和防火墙规则全部失效。这是因为网卡驱动加载后设备注册顺序和命名规则会基于 PCIe 槽位、MAC 地址或固件索引重新生成名字。# 备份当前网络配置文件RHEL 系 cp -a /etc/sysconfig/network-scripts/ifcfg-* /root/backup_ifcfg_$(date %F)/ cp -a /etc/NetworkManager/system-connections /root/backup_nm_$(date %F)/ # 记录当前接口与 PCI 地址的对应关系 ip -o link show | awk {print $2, $NF} ls /sys/class/net/ | while read iface; do echo $iface - $(readlink -f /sys/class/net/$iface/device | awk -F/ {print $(NF-2)}); done备份不只是留后悔药更是为了安装前后对比接口变化。/sys/class/net/下每个接口的device软链接会指到 PCIe 设备路径从路径里的0000:xx:xx.x可以反查接口对应哪个物理网卡。这一步还会帮你提前发现另一个问题如果系统里已经存在一套配置文件引用了旧接口名新驱动加载后接口名变化配置文件里DEVICEeth0与实际接口对不上NetworkManager 或 systemd-networkd 可能直接放弃配置表现为网卡起来了但没 IP。备份做完后即使发生这种状况也可以快速恢复或重写配置。4. 离线安装两种路径rpm 包与 dkms 源码编译4.1 通过 rpm 包安装适合 RHEL/CentOS 系的快速路径生产服务器通常不允许联外网驱动安装包以 rpm 文件形式拷贝到机器上是最常见的落地方式。包名一般是kmod-xxx-版本号.x86_64.rpm或kmod-net-xxx形式安装过程本身不需要网络。# 安装驱动 rpm 包不处理依赖 rpm -ivh kmod-net-xxx-1.0.0-1.el9.x86_64.rpm # 如果提示依赖缺失查找本地 rpm 包目录并批量安装 yum localinstall -y ./kmod-net-xxx-1.0.0-1.el9.x86_64.rpm # 刷新模块依赖信息 depmod -a # 加载驱动模块 modprobe netdrvrpm -ivh是直接安装如果系统里已存在同名旧版本包会报错提示冲突用-Uvh做升级会覆盖旧包。装完后必须执行depmod -a重新扫描模块目录并生成依赖文件modprobe才能按名字解析到这个新模块。如果安装包在 rpm 的 post 脚本里已经自动调用了 depmod重复执行成本也不高可以忽略。加载后立即验证模块是否与设备绑定# 查看模块加载状态 lsmod | grep netdrv # 确认设备已被驱动绑定 lspci -nnk | grep -i -A3 ethernet # 检查接口是否已创建 ip link show如果lsmod有模块但lspci -k仍然显示(none)说明设备没有被自动绑定常见原因是设备 ID 没有匹配上模块的 modaliases。此时先查设备的 vendor/device ID再看模块的modinfo netdrv输出的alias字段里有没有这个 ID或者直接手动绑定一次确认驱动本身可用。4.2 通过 dkms 源码包安装内核频繁升级环境的最佳选择测试环境或者有内核升级规划的机器上我更推荐用 dkms 方式安装厂商源码包。它的核心价值是内核从 A 版本升到 B 版本后dkms 自动为新内核重新编译模块不用你手动make make install避免每次升级后都要重装驱动的重复劳动。# 安装 dkms 框架RHEL 系仓库里有 yum install -y dkms kernel-devel gcc make # 解压厂商驱动源码包 tar zxf net-driver-src-1.0.0.tar.gz cd net-driver-src-1.0.0 # 将驱动注册到 dkms 框架模块名为 netdrv版本号 1.0.0 dkms add -m netdrv -v 1.0.0 # 编译并安装模块到当前内核 dkms build -m netdrv -v 1.0.0 dkms install -m netdrv -v 1.0.0 # 加载驱动 modprobe netdrvdkms add不是编译动作它只是把源码目录里的文件复制到/usr/src/netdrv-1.0.0/并注册到 dkms 数据库。dkms build才会真正执行编译这个阶段如果失败错误日志在/var/lib/dkms/netdrv/1.0.0/build/make.log排错要直接看这个文件而不是终端输出。编译过程中dkms.conf文件里的PACKAGE_NAME和PACKAGE_VERSION字段必须与add命令里的参数保持一致否则会报找不到配置的错误。源码包里如果没有dkms.conf不能硬套上面的命令说明厂商没有提供 dkms 支持需要按 tar 包的 README 手动编译安装。4.3 加载后的一连串确认动作不管哪个路径装完都需要确认三件事模块在运行的内核里、模块绑定了目标设备、网口有 MAC 地址并处于可配置状态。# 确认模块属于当前内核 modinfo netdrv | grep vermagic uname -r # 查看接口状态和 MAC 地址 ethtool -i eth0 ip link show eth0 # 查看驱动报告的速率和队列 ethtool eth0 | grep -E Speed|Duplex|Port ethtool -l eth0modinfo netdrv | grep vermagic输出的内核版本标记如果不等于uname -r的输出说明系统里存在为其他内核编译的模块副本。为什么 modprobe 会加载错版本因为/lib/modules/$(uname -r)/和/lib/modules/旧版本/里可能有同名文件而 depmod 的优先级短路了路径。ethtool -i能显示当前实际使用驱动的名称和固件版本这一步才是真正的“确认装对了”。加载完先不要急着配 IP先观察接口是否UP看dmesg尾部有没有链路相关的报错。如果接口状态是DOWN用ip link set eth0 up拉起后再确认因为某些网卡要求 link up 之后才完成固件初始化速率协商在 up 之前不会发生。5. 避坑海光网卡驱动安装最常见的5个翻车现场5.1 现象内核升级后网卡驱动“凭空消失”某台测试机执行了系统更新内核从 5.14 升到 5.15重启后ip link里只剩 lo。原因是之前用 rpm 方式安装的驱动模块是针对 5.14 编译的内核升级后模块文件所在的/lib/modules/5.14.x/目录被清理rpm -qa 还能看到包在模块文件却已经不在当前内核的模块树里。原因在安装方式kmod 类 rpm 只覆盖安装时的那个内核版本不会追随新内核自动构建。解决方法是重新安装驱动 rpm 包或者改用 dkms 方式从源码注册一次后续内核再升级都由 dkms 自动兜底。如果环境里多个内核版本共存建议用 dkms 而不是反复装 rpm。5.2 现象modprobe 报错 “Operation not permitted”一台启用了 Secure Boot 的服务器上modprobe加载厂商驱动直接报Operation not permitted但dmesg里没有明显的拒载原因执行modprobe -v也没有额外信息。这是模块签名校验失败的表现内核要求加载的模块必须有合法签名厂商未签名的模块被拒绝。解决有两条路。一是走 MOK 流程把模块公钥导入内核信任列表二是直接在 BIOS 里关掉 Secure Boot测试环境常用。在只能远程操作的机器上MOK 流程需要重启进入 shim 的 MOK 管理界面确认 key比较繁琐。更实际的建议装机阶段如果确认要装第三方驱动先关 Secure Boot 或准备好厂商提供的签名证书。5.3 现象编译时报错找不到 “linux/version.h”源码包make阶段报fatal error: linux/version.h: No such file or directory。这个头文件由 kernel-devel 包提供路径是/usr/src/kernels/$(uname -r)/include/linux/version.h。系统里虽然装了 kernel-devel但版本和当前内核不匹配比如当前内核 5.14.0-1装的确 5.14.0-2路径里的版本目录也对不上。处理办法是严格按uname -r安装同版本 kernel-devel。RHEL 系系统里如果 yum 源没有正好对应的版本先yum update kernel让系统升到跟包一致或者从厂商的 yum 源里找匹配版本。最容易忽略的是uname -r显示5.14.0-1.el9.x86_64时kernel-devel 的包名也是完整带-1.el9后缀的不能只匹配大版本号。5.4 现象加载了新驱动旧驱动还占着设备lspci -k显示设备被内核自带的通用网卡驱动占用厂商驱动 insmod 时也报Device or resource busy。这不是冲突是内核设备模型里同一时刻一个 PCI 设备只能被一个驱动绑定。厂商驱动没有主动接管设备的能力必须先让旧驱动释放。# 先卸载占用设备的旧驱动 modprobe -r 旧驱动模块名 # 把旧驱动加入黑名单防止下次开机自动加载 echo blacklist 旧驱动模块名 /etc/modprobe.d/blacklist-org.conf # 加载新驱动 modprobe netdrv # 重新生成 initramfsRHEL 系 dracut -fmodprobe -r卸载时如果提示Module in use说明有网络接口正在使用该驱动要先把对应网卡down掉或者干脆确认这台机器没有活跃业务后再动。黑名单文件要放在/etc/modprobe.d/下内核加载模块时会按该目录下的配置跳过指定模块。dracut -f是最后一步因为 initramfs 里可能包含了旧驱动不重建的话重启后旧驱动又在引导阶段被加载。5.5 现象装完驱动后接口名从 eth0 变成了 ens2f0系统里有配置文件写死DEVICEeth0驱动替换后接口名按 PCIe 拓扑重新生成变成ens2f0配置文件彻底失效IP 地址起不来。原因不是驱动 bug而是 systemd 的可预测命名规则基于 PCIe 槽位和设备路径生成接口名设备换驱动后暴露给 udev 的属性变化导致命名结果不同。解决方式是统一到 predictable naming 用新名字更新配置或者强制降级到传统eth0命名。后者要在/etc/default/grub里给内核加net.ifnames0 biosdevname0参数然后重新生成 grub 配置。我更建议换成新名字适配因为 predictable naming 是长期趋势临时改回 eth0后续再加网卡还会出新的命名问题。6. 装完不是终点从模块加载到重启不丢网卡驱动加载成功只算完成了一半真正的验收标准是重启后网卡还在、接口名稳定、链路速率符合预期、流量没有异常丢包。我习惯按顺序跑一遍自检先把链路层确认做扎实。ethtool -i确认驱动名称和版本后ethtool eth0看 Speed 是否协商到预期速率千兆口出 100Mb/s万兆口出 1Gb/s 都是典型的协商错误去查对端交换机端口和网线。然后看队列数量ethtool -l eth0里的 Combined 值如果只有 1 或 2而网卡芯片支持 8 队列以上说明 RSS 没有自动开启用ethtool -L eth0 combined 8调整。跑一轮实际流量验证驱动稳定性比看计数器更靠谱。iperf3 在内网打满带宽观察有没有重传率飙升和带宽跳水# 服务端接收端 iperf3 -s # 客户端发送端打满 60 秒并统计重传 iperf3 -c 目标IP -P 8 -t 60 -i 5-P 8起多个并发流是为了验证多队列场景下 CPU 会不会被单核打满。如果单流跑不满带宽但多流可以多半是 RSS 队列没有分散到多个 CPU检查中断亲和配置。如果多流也跑不满回看驱动模块是否有调整队列数量的参数。最后一步也是很多人最容易漏的重启验证。modprobe装的模块如果不写进持久化配置重启后并不会自动加载。厂商 rpm 包通常会在安装时自动处理持久化但 dkms 或手动编译方式很可能没有覆盖到。确认方法很简单重启后直接跑ip link如果接口还在就说明从 initramfs 或 modprobe.d 配置的自动加载路径生效了如果不在把模块名写进/etc/modules-load.d/netdrv.conf一行一个模块名重启已验证生效。现在我的习惯是任何机器装完网卡驱动当场测lspci -k、ethtool -i、ip link三个命令再重启一遍才敢交付。因为工作时间久了你会发现当场能用不算数重启后还在才是真稳定。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑