跳到主要内容

驱动诊断

概述

DarraRT 产品运行依赖三个内核态驱动: DarraRT.sysDarraRT_Eth.sysDarraRT_PLC.sys。 三者通过 GlobalIO Section 共享同一物理页, 实现零拷贝、零跨驱动调用的运行时协作。

驱动层一旦异常, 上层表现会非常多样: PDO 全零、WKC 恒错、Service 无法连接、 IOCTL 超时、Section 映射失败、系统崩溃 (BSOD)。本文档系统介绍驱动状态检查、 IOCTL 响应测试、DbgView 实时日志过滤、GlobalIO 映射验证、卸载/重装标准流程

适用场景

  • IDE/Service 报告 \\.\DarraRT* 设备打开失败
  • PDO 或 IO 显示全零 (Section 未映射)
  • 系统启动后 DarraRT 服务进入"已启动但不工作"
  • 升级驱动后功能异常
  • 偶发 BSOD

三驱动矩阵

驱动文件设备路径职责源码
DarraRT.sys\\.\DarraRT核心隔离 / SMI 检测 / GlobalIO Section 创建者 / TSC 校准Darra_RT_Driver/Global/WDK/
DarraRT_Eth.sys\\.\DarraRT_EthNDIS 协议驱动 / EtherCAT 帧 / PDO 线程 / 实例共享内存Darra_RT_Driver/Eth/WDK/
DarraRT_PLC.sys\\.\DarraRT_PLCPLC VM / IOMerge / Robot CyclicUpdateDarra_RT_Driver/PLC/WDK/

三驱动依赖与启动顺序

  1. DarraRT.sys         (Boot Start,   系统启动前加载)
|
| IOCTL_DARRT_CALIBRATE → 获取 TSC
| IOCTL_DARRT_ISOLATE_CORE → 注册隔离核
| ZwCreateSection → GlobalIO Section
v
2. DarraRT_Eth.sys (System Start, 启动时加载)
|
| ZwOpenSection + MapViewOfSection → 映射 GlobalIO
| NdisRegisterProtocol → 绑定网卡
v
3. DarraRT_PLC.sys (Demand Start, Service 触发)
|
| ZwOpenSection + MapViewOfSection → 同一物理页
| 启动 PLC VM 线程
v
[运行时: 三驱动通过 Section 指针直接读写, 零 IOCTL]

关键点: 第 2 步若失败, PDO 即便帧收发正常, 也无法传到 PLC; 第 3 步若 Section 映射 到不同物理页, 所有 IO 为零但无错误日志。

前置条件与工具

工具用途来源
sc.exe服务管理Windows 自带
DbgView.exe内核日志捕获SysInternals
devcon.exe设备管理WDK
WinDbg Preview崩溃转储分析WDK
poolmon.exe内存池监控WDK
SDV (Static Driver Verifier)驱动验证WDK

诊断步骤 (状态检查)

步骤 1: 服务管理器状态

# 查看三驱动服务状态
sc query DarraRT
sc query DarraRT_Eth
sc query DarraRT_PLC

预期输出:

SERVICE_NAME: DarraRT
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
...

判定规则:

  • STATE = 4 RUNNING → 正常
  • STATE = 1 STOPPED → 未加载, 看 WIN32_EXIT_CODEERROR_CODE
  • STATE = 7 PAUSED → 异常, 重启服务

步骤 2: 设备路径可达性

DarraDiag.exe (Service 附带的小工具) 测试:

DarraDiag.exe --device-test

预期输出:

Opening \\.\DarraRT ...         OK, handle=0x254
Opening \\.\DarraRT_Eth ... OK, handle=0x258
Opening \\.\DarraRT_PLC ... OK, handle=0x25C

或者用 PowerShell 的 P/Invoke:

Add-Type -TypeDefinition @"
using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles;
public class K32 {
[DllImport("kernel32", SetLastError=true)]
public static extern SafeFileHandle CreateFile(string p, uint a, uint s, IntPtr x,
uint c, uint f, IntPtr t);
}
"@
[K32]::CreateFile("\\.\DarraRT", 0xC0000000, 3, 0, 3, 0, 0)

步骤 3: IOCTL 响应测试

DarraDiag.exe --ioctl-test 会对每个驱动发送一个已知 IOCTL 并校验返回值:

IOCTL_DARRT_QUERY_VERSION       → 1.0.25200 OK (延迟 3μs)
IOCTL_DARRT_ETH_STATS → rx=12345 tx=12340 OK
IOCTL_DARRT_PLC_CYCLE_INFO → cycle=1000μs last=892μs OK

判定规则: 任一 IOCTL 超时 (>10ms) 或返回错误 → 看 DbgView 中对应驱动的异常日志。

步骤 4: GlobalIO Section 映射验证

三驱动必须映射到同一物理页, 否则零拷贝失效。

DarraDiag.exe --section-test

预期输出:

Global create section      : virt=0xFFFFCA01B8900000 phys=0x00000001BA000000 size=4096
Eth map view of section : virt=0xFFFFCA01B8900000 phys=0x00000001BA000000 MATCH ✓
PLC map view of section : virt=0xFFFFCA01B8900000 phys=0x00000001BA000000 MATCH ✓

Writing test pattern 0xDEADBEEF via Global ...
Reading from Eth: 0xDEADBEEF MATCH ✓
Reading from PLC: 0xDEADBEEF MATCH ✓

判定规则:

  • phys 三者相同 → 零拷贝 OK
  • phys 不同 → 严重问题, 通常是 Section 创建失败后, 每个驱动各自建了独立 Section
  • 写入校验失败 → Section 虚拟地址被改写, 看 Eth/PLC 的 Map 流程

步骤 5: DbgView 实时日志

以管理员权限启动 DbgView:

File → Capture Kernel (勾)
Edit → Filter/Highlight → Include: DarraRT;DarraRT_Eth;DarraRT_PLC

关注前缀:

前缀驱动说明
[DarraRT]Global隔离核 / TSC / Section
[DarraRT_Eth]EthNDIS / PDO / WKC
[DarraRT_PLC]PLCVM / IOMerge / Robot

正常启动序列:

[DarraRT]      driver entry, ver=25.2.0
[DarraRT] TSC CAL done, freq=3.6GHz skew=12
[DarraRT] Section created at 0xFFFFCA01B8900000
[DarraRT_Eth] driver entry, ver=25.2.0
[DarraRT_Eth] NDIS protocol registered: DarraRT_Eth
[DarraRT_Eth] Section mapped OK
[DarraRT_Eth] Bound to adapter {GUID}, linkspeed=1Gbps
[DarraRT_PLC] driver entry, ver=25.2.0
[DarraRT_PLC] Section mapped OK
[DarraRT_PLC] PLC VM thread started on isolated core 4

异常序列示例:

[DarraRT_Eth]  Section map FAILED: STATUS_OBJECT_NAME_NOT_FOUND

→ 说明 DarraRT.sys 尚未创建 Section (顺序错) 或名字不匹配 (版本不一致)。

诊断步骤 (深度)

步骤 6: 非分页池使用

# 管理员
poolmon.exe -p -i -bDREC,DRRC,DRPC

输出:

 Tag  Type     Allocs          Frees          Used         Diff
DRRC Nonp 1 200 1 199 4 KB +1
DREC Nonp 8 200 8 100 64 KB +100 <-- 泄漏?
DRPC Nonp 1 500 1 500 8 KB 0

判定规则: Diff 持续增长 → 该驱动有内存泄漏, 定位到对应 Tag 的 ExAllocatePoolWithTag 调用处。

步骤 7: 查看是否进入过 BSOD

Get-WinEvent -LogName System -MaxEvents 50 |
Where-Object { $_.LevelDisplayName -eq "Error" -and $_.ProviderName -like "*BugCheck*" }

如果有 BSOD 记录, 崩溃转储默认在 %SystemRoot%\MEMORY.DMP%SystemRoot%\Minidump\*.dmp。用 WinDbg 打开:

!analyze -v

关注:

  • MODULE_NAME 是否为 DarraRT*
  • STACK_TEXT 是否穿过 DarraRT 驱动
  • BUCKET_ID 是否有已知缺陷

步骤 8: 核心隔离状态

DarraDiag.exe --core-status

输出:

Total logical cores: 8
Isolated mask: 0x30 (core 4, 5)
Core 0: OS general , CPU usage 18%
Core 1: OS general , CPU usage 22%
Core 2: OS general , CPU usage 15%
Core 3: OS general , CPU usage 12%
Core 4: ISOLATED-PLC , CPU usage 100% (busy wait, correct)
Core 5: ISOLATED-ECAT , CPU usage 100% (busy wait, correct)
Core 6: OS general , CPU usage 8%
Core 7: OS general , CPU usage 11%

判定规则: 隔离核 100% 是正确的; 非隔离核若某个长时间 > 80% → 有后台进程抢资源。

驱动卸载 / 重装标准流程

严格按顺序: 停 Service → 停 PLC 驱动 → 停 Eth 驱动 → 停 Global → 卸载 → 重装 → 反向启动。

步骤 1: 停止用户态

# 停 IDE / Panel
taskkill /IM Darra.PLC.IDE.exe /F
taskkill /IM Darra.PLC.Panel.exe /F

# 停 Service
sc stop "Darra.PLC.Service"

步骤 2: 按逆序停止驱动

sc stop DarraRT_PLC
sc stop DarraRT_Eth
sc stop DarraRT

验证: sc query <name> 全部 STOPPED

步骤 3: 卸载

用官方卸载脚本 (绝对不要手动删 .sys, 会留下服务注册残留):

cd "C:\Program Files\DarraRT\Driver"
.\uninstall.ps1

步骤 4: 重装 (签名版本)

.\install.ps1 -InfPath .\DarraRT.inf
.\install.ps1 -InfPath .\DarraRT_Eth.inf
.\install.ps1 -InfPath .\DarraRT_PLC.inf

步骤 5: 按正序启动

sc start DarraRT
sc start DarraRT_Eth
sc start DarraRT_PLC
sc start "Darra.PLC.Service"

步骤 6: 验证

DarraDiag.exe --full-test

通过所有 6 项 → 可以投产。

异常模式速查表

现象根因定位方法解决
\\.\DarraRT 打不开驱动未加载sc query DarraRTsc start DarraRT
Section map failed启动顺序错DbgView 启动序列按序重启
PDO 全零Section 物理页不一致--section-test重启三驱动
IOCTL 超时驱动死锁WinDbg !locks收集 dump 报 bug
系统 BSOD驱动缺陷!analyze -v回退版本或报 bug
非分页池泄漏资源未释放poolmon Tag查对应 Tag 代码
隔离核 < 100%隔离失败--core-status检查 bcdedit
NDIS 未绑定网卡 GUID 变了Get-NetAdapter重置 Eth Service
签名失败测试签名未开bcdedit /enumtestsigning on
卸载后残留非标准卸载devmgmt.mscsc delete 清理

高级技巧

  • 驱动版本强一致: 三驱动必须同一编译批次, 头文件 dx_version.h 被三者共用, 版本号不一致时启动会报 VERSION_MISMATCH 拒绝映射 Section。
  • 测试签名模式: 开发阶段用 bcdedit /set testsigning on, 生产阶段必须 EV 代码签名。
  • WinDbg 实时附加: Win+R → dbgview 只看 DbgPrint, 如需逐行调试内核代码, 用另一台机器 USB/Net 内核调试连接。
  • Pool Tag 命名: DarraRT 内部约定 DRRC (Global) / DREC (Eth) / DRPC (PLC), poolmon 按 tag 过滤一目了然。
  • NDIS 双注册防护: Eth 用 "DarraRT_Eth" 作为协议名, 不与旧 Global 驱动冲突; 升级时若先旧版再新版可能双注册蓝屏, 务必先卸载旧版再装新版。

相关文档

三驱动协作示意