我帮一台工控机装Ubuntu 18.04,CPU是Intel第八代,板载网卡就是i219-LM。系统装完进桌面,网卡灯不亮,ip a里只有lo,当时第一反应是BIOS里把网卡关了,进BIOS翻了一圈发现功能正常。折腾了大半天,最后定位到是Ubuntu 18.04默认内核4.15里自带的e1000e驱动版本太老,认不出这块后续步进的i219-LM网卡,必须手动编译新版Intel官方驱动。这篇文章就是把这套排查和编译流程完整记录下来,给同样被这块网卡卡住的读者一个可以直接照做的方案。
整个过程不复杂,核心就是下载Intel官方e1000e驱动源码、安装编译环境、make install装好模块、最后用DKMS让它在内核升级后还能继续工作。适合遇到网卡完全识别不到、或者识别到了但没有网络接口的Ubuntu 18.04用户,也适合所有在Linux下被Intel板载网卡兼容性问题困扰的人。我会把每一步的为什么也讲清楚,不只是给你一串命令。
1. 先搞清楚:这块网卡为什么在Ubuntu上“失联”
1.1 连lspci都看不到?先区分三种故障层次
遇到板载网卡不工作,别急着找驱动,先按层次排查。第一层是BIOS/UEFI层面,这层有问题的话,操作系统根本看不到这个PCI设备;第二层是PCI总线枚举层面,lspci能看到设备,但内核没有匹配的驱动模块;第三层是驱动加载层面,驱动模块存在且和硬件ID匹配,但如果加载失败,一样没有网络接口。
我说的这台工控机属于第二层,lspci能看到Ethernet controller: Intel Corporation Ethernet Connection (14) I219-LM,但内核没有加载任何网卡驱动,所以没有生成对应的网络接口。这里有个细节,lspci -nn能看到设备ID,比如8086:15bd,前面是厂商ID,后面是设备ID。这个设备ID在后面的驱动源码核对环节非常重要,先记住它。
如果你连lspci都看不到这块网卡,先回BIOS确认是不是被禁用了,或者是不是启用了Intel AMT/Manageability Engine的某些独占功能。这类问题我在戴尔和联想的商用机上遇到过,BIOS里有一项“Intel AMT”或“Manageability”,开启后网卡资源会被管理引擎占用,Linux下就可能直接消失。遇到这种情况,先关掉相关选项再继续。
1.2 根因:e1000e驱动与内核硬件ID列表不匹配
不卖关子,问题的直接原因就是Ubuntu 18.04默认内核太老。Ubuntu 18.04发布时对应Linux 4.15内核,4.15里面自带的e1000e驱动版本大概是3.2.x或3.4.x。Intel的i219-LM网卡已经迭代了很多硬件版本,从设备ID15b7、15b8一路走到15bd、15be甚至更新。
Linux内核里,驱动模块对硬件的支持方式是写死一张设备ID列表。你在一个3.4版源码的hw.h里搜索15bd,很可能搜不到,或者搜到了但对应代码对后续步进的支持不完整。于是内核虽然认出了PCI设备,但找不到能匹配的驱动,结果就是没有网络接口。Windows下没这个问题,因为Intel给Windows提供的是独立的驱动安装包,更新走驱动更新渠道;Linux下的驱动是跟内核走的,不折腾的话只能等发行版升级内核。
如果你装的是Ubuntu 18.04后期版本并且用了HWE内核(比如5.4),这个问题大概率不会出现。但很多人用18.04就是为了配ROS Melodic、老版本CUDA、或者某些工控软件,内核版本被锁死在4.15,那就只能走编译驱动这条路。明白了这个原理,后面所有操作就都顺理成章了。
2. 动手前准备:驱动版本、编译环境与离线拷贝方案
2.1 选对驱动源码版本(这步最容易被忽略)
我们用的是Intel官方开源的e1000e驱动,源码包从Intel下载中心找,搜索关键词e1000e就能看到。版本号现在应该是3.8.x系列,很多教程还在用远古的1.x、2.x版本,那些版本对新网卡照样不认。我写这篇文章时用的是e1000e-3.8.4.tar.gz,你下载的时候官网可能会有更新的子版本,优先选最新稳定版。
选版本的原则只有一条:越新越好,但不要选RC、Beta之类的测试版本。e1000e是Intel千兆网卡的通用驱动,3.8.x基本覆盖了从i217到i226这些后续型号,i219-LM肯定在支持列表里。下载完成后先别急着解压,用另外一个能上网的机器把文件准备好。
下载地址可以在Intel官网下载中心搜索e1000e,找到文件名形如e1000e-3.8.4.tar.gz的Linux驱动包。文件不大,大概几百KB,里面没有一堆编译好的二进制,只有源码,需要在自己机器上编译成内核模块。
2.2 编译环境:内核头文件与基础工具链
编译内核模块不是普通的C语言编程,它需要当前内核的头文件,也就是/lib/modules/$(uname -r)/build目录。这个目录本质上是软链接,指向对应内核版本的linux-headers源码树。如果你的机器上没有这个目录,后面make几乎一定报错。
正常情况下安装编译工具链就两条命令:
sudo apt update sudo apt install build-essential linux-headers-$(uname -r)但注意,咱们现在网卡不能用,机器大概率连不上网,apt update本身就执行不了。我当时的处理方式是:主板上还有一个Realtek千兆网口,可以正常识别,所以编译依赖是在那台机器上直接在线装的。如果你运气差到只有一个网口,那就用USB外接网卡临时救急,或者找一台同架构能联网的机器,下载对应的deb包再拷贝过来安装。
如果你选择在另一台机器上下载deb包离线安装,需要这几个关键包:build-essential、gcc、make、linux-headers-generic以及对应的linux-headers-4.15.0-xxx-generic。使用apt download加依赖收集工具,或者直接用一个能联网的Ubuntu 18.04虚拟机,把apt缓存里的deb拷出来。
这里有个容易踩的坑:linux-headers包的版本必须和当前运行内核完全一致。你运行uname -r得到4.15.0-213-generic,装的headers也必须是这个版本。差一个编号,/lib/modules/4.15.0-213-generic/build就会指向不存在的目录。
2.3 没有网络怎么下载:离线迁移方案
很多人在这一步就卡住了:网卡没驱动上不了网,上不了网就没法下载驱动源码,没驱动文件就永远解决不了问题,成了一个死循环。破局方法其实不复杂:用另一台能联网的机器下载文件,U盘拷过去。这是最朴素也最有效的方法。
具体来说,你在任何一台有网的电脑上,访问Intel下载中心拿到e1000e-3.8.4.tar.gz,拷进U盘。然后把编译环境准备好,再拷贝源码包到目标机器的家目录或/tmp下。如果编译依赖也没装,一并把deb包拷贝过去,用sudo dpkg -i *.deb去装,遇到依赖报错就继续补包,一般也就十来个包。
另外一个更省事的思路:装系统的时候用18.04的Desktop镜像,Live环境里通常自带dkms、build-essential和大部分内核头文件。你可以启动到Live模式,挂载硬盘,把驱动编译好了再装进去。操作上比U盘拷deb要复杂,适合那种既没有第二个网口、也没有USB网卡、机器还特别难拆的特殊场景。不过对大多数人来说,临时借一个USB网卡是最快路径,十几块钱的USB百兆网卡在Linux下一般都能免驱。
3. 正式编译:源码解包、make与模块安装
3.1 解压与查看源码结构(先确认设备ID在不在支持列表)
所有准备工作做完,开始正式操作。先把源码包解压:
cd ~ tar -zxvf e1000e-3.8.4.tar.gz cd e1000e-3.8.4 ls你会看到src、COPYING、README等文件和目录。真正的驱动源码和Makefile都在src目录里。我强烈建议你花两分钟翻一下这个目录下的README,官方文档把编译步骤、DKMS用法、常见问题都写在里面了。很多人一上来就make,遇到问题再乱试,其实README早就写过正确做法。
进入src目录后,先做一件事:核对你的网卡设备ID在不在驱动支持列表里。
cd src grep -n "15bd" hw.h如果你的网卡是i219-LM,刚才lspci -nn看到的设备ID可能是15b7、15bb、15bd中的一个。比如我这边看到的是:
00:1f.6 Ethernet controller [0200]: Intel Corporation Ethernet Connection (14) I219-LM [8086:15bd] (rev 11)那么在hw.h里如果搜到了类似#define E1000_DEV_ID_PCH_LPTLP_I219_LM15 0x15BD这样的定义,说明驱动软件层面认这块卡,可以放心往下走。如果搜不到,那问题就严重了,你需要换更新的驱动版本,或者考虑直接升级内核到HWE版本。
3.2 编译安装:make与make install的完整动作
核对完硬件ID,开始编译。先确保你在src目录下,然后:
make编译过程不会很长,几十秒到一两分钟。内核模块不像大型应用程序,其实就是一系列C文件加几个头文件,生成一个.ko文件。如果编译过程没有报错,你会看到类似LD [M] .../e1000e.ko的输出。
编译成功之后,安装:
sudo make installmake install做的事情是把e1000e.ko拷贝到当前内核的模块目录,通常位置是/lib/modules/$(uname -r)/updates/dkms或者类似路径,然后自动执行depmod -a更新模块依赖。这里有一个很多人不注意的点:如果之前有过一次失败的编译,或者Makefile读到缓存,最好先执行一遍make clean再重新make,避免用到旧的中间文件和无效的模块符号信息。
另外值得说的是,整个编译过程并不会破坏你现有的内核。它只是在模块目录里新增了一个.ko文件,不会替换系统自带的任何核心文件。如果你担心搞坏系统,这种担心是多余的。真正需要注意的是驱动模块加载时的安全校验,这个放到后面第四章详细讲。
3.3 加载驱动并验证:modprobe、ip link、ethtool
驱动编译安装好,下一步就是加载。Linux加载模块有两个命令:modprobe和insmod。insmod是直接加载指定路径的模块文件,modprobe会先查模块依赖和配置,再加载。这里用modprobe更正规:
sudo modprobe e1000e执行完没有输出就是成功。然后验证一下:
ip link在我这台机器上,执行完立刻出现了enp0s31f6这个接口。注意这个名字,不是老教程里的eth0。Ubuntu 18.04用的可预测网络接口命名规则,i219-LM在PCI总线位置固定为00:1f.6,所以名字就是enp0s31f6。看到类似enp0s31f6: <NO-CARRIER,BROADCAST,MULTICAST,UP>的输出,说明驱动已经认出硬件了。如果网线插着,状态应该是LOWER_UP。
再用ethtool确认物理链路:
sudo ethtool enp0s31f6输出里的Link detected: yes就说明一切正常。这时候可以配置IP验证网络了。测试网络连通性最快的方法是让接口自动获取地址:
sudo dhclient enp0s31f6然后ping 8.8.8.8或者ping baidu.com(DNS如果没配置好,先ping IP)。能通,说明问题彻底解决。如果不想依赖DHCP,就直接修改/etc/netplan/01-netcfg.yaml配置静态IP,然后sudo netplan apply。
这里也要提醒一句,如果加载后依然没有网络接口,先不要急着reboot,重启之后可能问题照旧而你失去了现场。先把dmesg | grep e1000e的输出记录下来,这个日志对于排查注册失败的原因非常关键。
4. 让驱动长久稳定:DKMS、Secure Boot与内核升级避坑
4.1 用DKMS登记驱动,避免升级内核后再次失效
刚才的make install虽然解决了眼前的问题,但有一个隐患:它只把模块装进了当前内核的目录。假如某天你想起来执行apt upgrade,系统把内核升级到了4.15.0-214-generic,新内核目录里没有e1000e.ko,网卡又会被打回原形。
解决办法是用DKMS(Dynamic Kernel Module Support)来管理这个模块。DKMS的逻辑很简单:模块源码在系统里保留一份,每当有新内核被安装,DKMS自动把源码编译一次,装进新内核的模块目录。这样升级内核之后,网卡驱动依然能用。
e1000e官方源码对DKMS支持得很到位,3.8.x版本在src目录下直接提供了dkms_install目标:
sudo make dkms_install你也可以手动操作来加深理解。先建立源码目录:
sudo mkdir -p /usr/src/e1000e-3.8.4 sudo cp -r ~/e1000e-3.8.4/* /usr/src/e1000e-3.8.4/然后在/usr/src/e1000e-3.8.4/下写一个dkms.conf:
PACKAGE_NAME="e1000e" PACKAGE_VERSION="3.8.4" BUILT_MODULE_NAME[0]="e1000e" DEST_MODULE_LOCATION[0]="/updates" MAKE[0]="make -C src" CLEAN="make -C src clean" AUTOINSTALL="yes"最后执行注册和安装:
sudo dkms add -m e1000e -v 3.8.4 sudo dkms build -m e1000e -v 3.8.4 sudo dkms install -m e1000e -v 3.8.4dkms status能看到模块状态,显示installed就OK了。之后每次升级内核,DKMS会在新内核安装时自动把模块构建出来。这个机制值得所有需要手动编译驱动的人学习,不只是e1000e,很多网卡、显卡、虚拟化模块都可以用DKMS管理。
4.2 Secure Boot导致的模块加载失败:两种解决路径
如果你执行modprobe e1000e时收到类似Operation not permitted或Required key not available的报错,第一反应应该是查Secure Boot。我在另一台联想机器上就遇到过:驱动编译安装一切正常,但一加载就被系统拒之门外。
查看状态:
mokutil --sb-state如果输出是SecureBoot enabled,那就对上了。UEFI安全启动会对加载到内核空间的模块做签名校验,我们自己编译的模块没有可信签名,会被拒绝。解决的路径有两条。
第一条,最省事:进BIOS/UEFI设置,把Secure Boot关闭。重启之后模块就能正常加载。这种方案的代价是系统少了一层安全引导校验,对于绝大多数个人电脑和工控设备来说可以接受。
第二条,正规但稍麻烦:给模块签名,并把签名密钥注册到MOK(Machine Owner Key)列表。生成签名密钥的命令:
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=My Module Signing Key/" sudo mokutil --import MOK.der这一步会让你设置一个一次性密码,重启后进入蓝色MOK管理界面,选择Enroll key,输入密码完成密钥注册。系统重启后再给编译好的.ko文件签名:
sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 MOK.priv MOK.der /lib/modules/$(uname -r)/updates/dkms/e1000e.ko然后modprobe e1000e就能通过了。注意,如果后续使用DKMS重新编译了模块,需要重新签名一次。这一套流程在网上下载的很多驱动教程里都不会提,但实际生产环境里碰上Secure Boot的概率真不低。
4.3 内核升级后驱动失效的处理惯性
即使装了DKMS,还是有人会遇到驱动失效的情况。最常见的原因是升级内核之后DKMS构建失败。打开日志看:
sudo dkms status sudo cat /var/lib/dkms/e1000e/3.8.4/build/make.log构建失败通常是因为linux-headers没装。Ubuntu升级内核的时候,不一定自动安装对应的headers包。如果你用的是HWE内核,尤其容易出现这个情况,因为HWE内核的headers包名和GA内核不一样。
解决办法是把内核头文件包固定安装上:
sudo apt install linux-headers-generic linux-headers-$(uname -r)装完再手动触发一次DKMS构建:
sudo dkms build -m e1000e -v 3.8.4 sudo dkms install -m e1000e -v 3.8.4如果你完全不想在升级内核这件事上费心,也可以退出DKMS方案,直接锁定内核版本,不升级内核。生产环境有时候就是这样的思路,稳定性优先。但如果你想让系统保持可维护性,DKMS加上自动安装headers,才是长期正确的玩法。
5. 常见问题速查与实操心法
5.1 常见报错速查表
实际操作中会遇到各种各样的问题,我整理了一个常见问题速查表,基本覆盖了这篇博客方案里大部分翻车场景。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
lspci看不到网卡 | BIOS禁用或AMT占用 | 进BIOS开启网卡,关闭AMT相关选项 |
lspci能看到但无网卡接口 | 驱动未匹配或未加载 | 确认设备ID,编译安装新版e1000e |
make报错找不到linux/version.h | linux-headers未安装 | 安装与当前内核版本一致的headers包 |
make在源码根目录执行报错 | 未进入src目录 | 进入src目录再执行make |
modprobe报Operation not permitted | Secure Boot拦截 | 关闭Secure Boot或签名模块 |
模块加载成功但Link detected: no | 网线未插好或对端设备未就绪 | 插好网线,检查交换机/路由端口 |
| 重启后网卡又消失 | 驱动未注册到DKMS | 重新执行make dkms_install或用dkms命令注册 |
| 内核升级后驱动失效 | DKMS未自动构建成功 | 安装headers,手动执行dkms build/install |
这张表其实也是一个排查路径。从上往下走,一层一层定位,绝大多数问题都能在十分钟内找到头绪。
5.2 几个文档里不会写的经验
第一,如果条件允许,优先用系统自带的HWE内核。Ubuntu 18.04.5之后的HWE内核版本是5.4,自带的e1000e驱动支持i219-LM已经非常成熟。虽然内核版本锁死导致要编译驱动的情况确实存在,但在动手之前,先问自己一句:真的不能升级内核吗?如果答案是能,那整个编译流程都可以省掉。我帮人处理问题时经常发现,他们不升级内核只是因为担心软件不兼容,但实际上很多软件在新内核下跑得好好的。
第二,编译驱动时最好保持同一内核版本直到确认稳定。驱动编译依赖内核头文件,每次内核升级都可能让之前编译的模块失效。在你确认整套方案无误之前,可以先不动内核,等驱动运行了几天、确认没问题了,再考虑后续的内核升级策略。
第三,网卡接口名字是enp0s31f6而不是eth0,这是Ubuntu 18.04的正常命名规则。不要花时间去找配置文件改成eth0,除非你有特殊需求。如果一定要统一命名,需要在内核启动参数里加net.ifnames=0,但现代Linux服务器环境不推荐这么干。
第四,如果你的主板有多个网口,不妨把i219-LM和其他型号的网卡分开看待。很多商用主板是i219-LM加Realtek 8111系列双网卡,Realtek的驱动在内核里一般都有且较新。先用能用的网口把系统更新做完,再回来折腾i219-LM,能少很多离线安装依赖的麻烦。
第五,真正的老手处理这个问题的逻辑是:先查内核模块的硬件ID表,再决定是升级内核还是编译驱动,而不是盲目下载最新驱动一顿乱装。你可以在任何一台Linux机器上通过/usr/src/linux-headers-$(uname -r)/drivers/net/ethernet/intel/e1000e/hw.h查看当前内核的e1000e支持列表,对比自己网卡的设备ID,这一步能让你在五分钟内判断问题是否跟驱动相关。
我在实际处理这类问题时的体会是,网卡驱动编译这件事,看着像是个硬件兼容性小问题,背后其实牵扯到Linux内核模块机制、UEFI安全校验、DKMS管理、发行版内核策略,一个点没弄明白就会被卡住半天。但按照“先定位层次、再核对设备ID、然后编译安装、最后注册DKMS”的顺序走一遍,你不但能修好这块网卡,以后遇到其他网卡、USB设备、显卡驱动类似的问题,也都有了通用的排查思路。最后提醒一句:整个过程最考验耐心的是离线环境下准备编译依赖,先把这一步搞定,后面一路都是顺的。