niko 加载中
0%

为什么一块「从没碰过」的网卡,能冻住游戏和视频

一块我从没碰过、连网线都没插的网卡,是怎么让游戏和视频一起卡住的

作者天镜发布于技你太美技术随笔硬件排障aigc辅助

***

先说那天晚上发生了什么。

我在玩原神,跑图跑到一半,画面停住了。

不是掉帧那种停,是整幅画面僵在那儿,像有人按了暂停键。同一瞬间,耳机里传出一声「滋滋」,大概持续了两百毫秒。然后一切照常,仿佛什么都没发生。

我当时的第一反应是显卡,第二反应是散热,第三反应是「这游戏又抽风了」。

第二天我看视频,B站客户端,看着看着画面停一下,声音跟着抽一下。于是这件事从「游戏的问题」升级成了「我这台电脑的问题」。

它出现的节奏很讨厌:三秒一次到十二秒一次都有,毫无规律,让人抓不住。我一度以为是自己在疑神疑鬼,直到我拿秒表掐了几次,发现确实有。

……

先说清楚这故事有多离谱

我后来花了一个晚上,把凶手揪出来了。

它是一块网卡。

一块我从没插过网线、状态显示「未连接」、日常完全用不到的 2.5G 有线网卡——Realtek 的 RTL8125。

它每 2.214 秒把自己重置一次,从不缺席,波动不超过八毫秒。而每一次重置,都可能让整台机器停住大约 0.2 秒。

一块你从来没碰过的网卡,凭什么冻住你的游戏和视频?

这件事我一开始完全想不通。后来想通了,而且想通之后觉得挺荒诞的。这篇就讲这一件事。

一分钟原理版

先把结论摊开,不绕。

网卡的驱动不是一个”你联网的时候才启动的程序”。它是一个内核态的常驻驱动,开机即加载,然后一直在后台做一个动作:每隔固定时间,通过 PCIe 去读一次网卡的硬件寄存器,看看链路和 PHY 正不正常。

这跟你有没有插网线、有没有连 WiFi、有没有联网,一点关系都没有。 驱动在那里,这个轮询就在那里。

而在我的机器上,它每次读回来的是——报错。

驱动一看:坏了,设备不正常。于是它发起一次「设备重置」。

这个重置不是软件里清个标志位那么简单,它要走一条正经流程:设备复位 → 由 Windows 的 PCI 总线驱动执行复位 / PCIe 链路重训练 → 重新枚举、重新初始化。

问题就出在这条流程上:它是一条全局串行的路径。 PCI 总线驱动、ACPI、电源管理之间要互相加锁协调,谁都不能插队。在那两百毫秒里,其他驱动只能排队等着。

排队的队伍里包括谁呢?

包括显卡驱动,它正准备把下一帧送出去。也包括声卡驱动,它每十几毫秒就必须往音频缓冲区喂一次数据。

它们跟网卡毫无关系,却必须一起等那把锁。

因果链:网卡常驻轮询 → 链路报错 → 驱动重置设备 → 全局锁停顿 → 画面停住 0.2 秒、音频缓冲欠载爆音

于是就有了我看到的现象:

  • 声卡的缓冲区没等到数据,欠载(underrun)了。播放器只能重复或者丢弃采样——这就是那声「滋滋」。
  • 显卡的那一帧没按时送到合成器。画面上就出现了那个僵住的瞬间。

一秒二十三毫秒的病灶,两百毫秒的症状。就这么来的。

我是怎么把凶手揪出来的

我很清楚,靠”感觉卡了一下”是找不到东西的。得先量化,再找对应。

四步。

四步取证:抖动探针抓冻结 → 换算墙上时刻 → 对齐系统事件日志 → 用 WHEA 与 PCIe 拓扑定位设备

① 先给它装一个秒表

写一个 8 毫秒步进的循环,每睡 8 毫秒就记一下实际过了多久。正常情况应该稳定在 15 毫秒上下(Windows 的时钟精度就那样),一旦某次超过 40 毫秒,就说明这一瞬间整个系统被冻住了。

跑 200 秒,抓到三次:

45.30 秒 —— 207.1 毫秒
87.34 秒 —— 207.7 毫秒
175.92 秒 —— 209.8 毫秒

三次的时长几乎一模一样。这个「几乎一模一样」非常关键——它不是资源争抢,资源争抢不会这么整齐。它是一个固定的超时或者看门狗机制。

② 把相对秒数换算成墙上时刻

脚本启动的时候先记一个真实时间,之后把相对秒数加上去,就得到三次冻结的绝对时刻。

③ 去系统事件日志里查那几秒

这是破案的一步。查每一秒前后 ±8 秒的全部事件,然后我看到了这个:

Realtek Gaming 2.5GbE Family Controller is reset by ESD timer.

而且它出现得极其有规律——每 2.2 秒一条。我把统计跑出来:

最短间隔 2.2060 秒
最长间隔 2.2230 秒
中位间隔 2.2141 秒

波动八毫秒。 这不是人的操作能造成的,这是驱动里一个写死的定时器。

三次冻结,网卡重置事件分别出现在冻结窗口开始后的第 155、150、151 毫秒——全部落在窗口里面。三次独立事件,偏差都在同一个量级上,这就不是巧合了。

④ 确认到底是哪块设备

日志里还有个线索:WHEA(Windows 硬件错误架构)报了上千次「已纠正的硬件错误」,组件是 PCI Express Root Port,位置是总线 0、设备 1、功能 6。

这是个”函数”级别的位置,得知道它后面挂了谁。把这条总线上的设备挨个枚举出来:

位置挂的是什么
0
.1
NVIDIA RTX 5070 Ti Laptop GPU
0
.4
MediaTek Wi-Fi 6E MT7922
0
.5
NVMe SSD
0
.6
Realtek Gaming 2.5GbE

两层证据,指向同一个东西。

证据长这样

三次冻结的对齐图:207.1、207.7、209.8 毫秒三条冻结色块,网卡重置事件都发生在窗口开始后约 150 毫秒处

上图就是最终说服我自己的那张。三条红块是我感知到的卡顿,青色竖线是日志里网卡重置的时刻。你可以看到它总是稳稳地落在红块内部靠前的位置。

还有个数字更能说明问题。这块网卡的错误事件有多少条?

时间事件数
9 月 23 日之前0
9 月 24 日3,650
9 月 25 日(仅一小时)10,880

二十四小时内,它刷了 14,545 条日志,占了整个系统日志事件的 99%。

这里有个副作用挺讨厌的:Windows 系统日志默认是 20MB 的循环覆盖,被这么一冲,9 月 18 日之前的历史记录全被挤掉了。所以我很想回头看”第一次卡顿那天到底发生了什么”——抱歉,日志没了。

顺便交代两个排除项,因为方向错了很浪费时间:

  • 我用 xperf 做了 200 秒内核追踪。DPC 总数 732,329 次,其中图形内核 dxgkrnl.sys 占了 53.5%(每秒 1960 次,偏高)——我一度以为就是它。
  • 但追踪显示,DPC/ISR 的占用率从来没超过 5%,单次最长的 DPC 只有一两毫秒。两百毫秒的冻结,不可能由一个两毫秒的 DPC 造成。

所以图形驱动那边是”有点忙”,但不是凶手。数字对不上的东西,再像也要放掉。

至于为什么”没碰过它也会卡”,机理是这样:

内核锁机理:网卡驱动轮询 → 触发设备重置并持有全局锁 → 显卡送帧与声卡喂缓冲在锁外排队 → 画面停与音频爆音

藏起来的几个决定

关于修法。 最干脆的办法当然是”把这块网卡禁掉”。零风险,一秒生效,我甚至已经这么验证过了——禁掉之后,150 秒内冻结次数是 0。

但我犹豫了一下。因为禁掉它只是把问题藏起来,我并不知道它为什么会变成这样。而且万一哪天我真要用有线网呢。

所以我换了个更温和的方向:进网卡的高级属性,把几个省电相关的开关关掉——环保节能(Green Ethernet)、Gigabit Lite、EEE、还有一堆网络唤醒。然后重启网卡让设置生效。

结果:错误事件从每分钟 135 条降到 0。网卡照常启用、照常可用。

我猜机理是这样:这类省电特性会让 PHY 进入低功耗状态、改变链路行为,而在一块没插网线的网卡上,驱动那个看门狗容易把它误判成异常,于是反复重置。关掉之后链路不再进那个状态,风暴就停了。

关于保留证据。 那两百秒的内核追踪文件有 552MB,我留在硬盘上了。不是舍不得删,是想万一复发,还能拿这次的数字做对照。

我踩的坑

必须写这一节,而且这次的坑是我自己挖的。

第一个坑:我以为改设置没用。

第一次测试的时候,我调用改属性的命令,加了一个参数叫 -NoRestart。

结果改完一测——错误事件数一点没变,还是每分钟 135 条。我当时的结论是”这条路走不通,省电特性不是原因”,差点就转头去搞重装驱动了。

后来才反应过来:那个 -NoRestart 的意思是”只写进注册表,先别重启网卡”。 也就是说,我是把一个”设置了但还没生效”的状态,当成了”设置了但没用”。

加上重启网卡之后,同样的设置,事件数直接归零。

一个参数没读明白,差点让整个排查方向跑偏。

第二个坑:我先怀疑了错的人。

前面说了,追踪里 dxgkrnl.sys 的 DPC 数字特别扎眼。我在这上面花了差不多四十分钟,翻图形栈、查混合输出、怀疑向日葵的虚拟显示器驱动……

直到我把 DPC 的耗时分布拉出来——最长一两毫秒——才意识到方向错了。一个两毫秒的东西,解释不了两百毫秒的停顿。

这两件事教我的都不是技术,是习惯:别把一个没验证的假设当成结论,哪怕它看起来很像。

如果你也中招

一样的症状:画面周期性停约 0.2 秒、音频同时爆音、玩游戏和看视频都中、清灰和重装显卡驱动都没用。

先确认一下有没有第二个。如果事件查看器里能看到那条 is reset by ESD timer,那基本就是它了。

处置顺序(管理员权限):

# 1. 列出所有网卡,找到那块的名称
Get-NetAdapter

# 2. 关掉省电相关开关(把 "以太网" 换成你的网卡名)
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword EnableGreenEthernet -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword GigaLite            -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword '*EEE'             -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword AdvancedEEE         -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword '*WakeOnMagicPacket' -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword '*WakeOnPattern'     -RegistryValue 0 -NoRestart
Set-NetAdapterAdvancedProperty -Name "以太网" -RegistryKeyword S5WakeOnLan          -RegistryValue 0 -NoRestart

# 3. 关键一步:重启网卡,让上面的设置真正生效
Restart-NetAdapter -Name "以太网"

# 4. 验证:看接下来一分钟还有没有新事件
Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='rt25cx21';StartTime=(Get-Date).AddMinutes(-1)}

驱动名不一定是 rt25cx21,用事件查看器里看到的那个提供程序名替换。

老实交代局限:

我这套办法关掉的是”触发条件”,不是”根本原因”。那块网卡的 PCIe 链路层曾经报过上千次已纠正的硬件错误,说明链路本身可能就有问题。如果哪天我插上网线之后它又开始了,那下一步就该从机械革命官网装本机型对应的网卡驱动,或者升级 BIOS——这两样在 PCIe 链路问题上经常真能修。

再有,日志被我前面说的那场洪水冲掉了一部分历史。所以”第一次卡顿那天到底装了什么”,我也说不准,只能推测是 9 月上旬链路开始变坏,看门狗从偶尔触发变成无限循环。

后记

修完那天我把追踪关掉,重新打开视频,看了十分钟。

没有「滋滋」了。

说实话,那一刻的感觉挺怪的。我折腾了一晚上,写了一堆脚本,翻了几万条日志,最后做的事情是——在一个我从没打开过的设置页里,关掉了两个我从来没听说过的选项。

但这就是这件事有意思的地方。

一台电脑里住着几百个驱动,绝大部分你一辈子都不会主动碰。它们安静地待在内核里,做着自己那一件事。它们之间不归你管,但它们会互相影响。 那块网卡从来没打算害我,它只是坏了一点点,然后一直很努力地、每 2.214 秒提醒所有人一次。

而我能做的,就是学会看它留下的痕迹。

感谢你的聆听。

为什么一块「从没碰过」的网卡,能冻住游戏和视频

https://blog.8765777.xyz/posts/post-20260925-rt25cx/

作者天镜发布于许可协议CC BY-NC-SA 4.0
距今已经过去