ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

NDIS6 Miniport驱动开发实战:从环境搭建到收发帧闭环

NDIS6 Miniport驱动开发实战:从环境搭建到收发帧闭环 简介本资源是一份面向Windows驱动开发初学者与进阶工程师的NDIS 6网络驱动学习实践包聚焦于Miniport/Filter类驱动开发核心流程解决NDIS驱动环境搭建、数据包收发、电源管理及错误处理等典型开发难题。压缩包共133个文件含10个C源文件如filter.c、tcp.c、ip.c、ethernet.c等、10个头文件、6个INF安装配置文件、2个SYS驱动二进制文件以及大量编译中间产物tlog/obj/pdb完整覆盖从源码编写、WDK编译到签名调试的全链路工程结构。资源大小为19.39MB目录组织规范便于理解NDIS 6模块化编程模型与分层驱动架构。已有215人学习下载读者可直接获取可编译运行的NDIS 6驱动框架代码、配套INF安装脚本、关键协议栈处理逻辑ARP/ICMP/TCP/UDP实现范例以及预编译调试所需的符号文件与日志支持是深入理解Windows网络内核机制与动手开发合规驱动的实用入门素材。1. NDIS6 驱动开发不是“解压 zip 就能用”它本质是 Windows 内核级网络协议栈的接入契约专为高性能、低延迟、可扩展的网卡驱动而设计适用于需要绕过 Winsock 层直接操控数据帧如虚拟交换机、抓包引擎、DPDK 替代方案、防火墙内核模块的场景。很多工程师第一次看到ndis.zip_ndis_ndis6驱动_zip这类命名文件时误以为是“驱动安装包”双击运行后蓝屏或设备管理器报错 0x0000007ESYSTEM_THREAD_EXCEPTION_NOT_HANDLED根本原因是NDIS6 不是即插即用的 INFSYS 组合包而是一套需严格遵循微软接口规范、在 WDK 环境下编译、签名、加载的内核模式驱动框架。它不兼容 Windows XP/2003NDIS5最低要求 Windows Vista SP1 及以上且必须通过inf2cat签名、devcon或pnputil安装绝不能靠手动复制.sys文件到System32\drivers下启动。本文面向已掌握 C 语言、Windows 驱动基础、熟悉 WDK 构建流程的中级开发者目标是从零构建一个可加载、可绑定、能收发原始以太网帧的最小 NDIS6 Miniport 驱动并避开 90% 新手在NdisMRegisterAdapterEx、NdisMIndicateStatusEx和MiniportInitializeEx中踩过的内存模型与 IRQL 坑。2. 搭建 NDIS6 开发环境不是装个 Visual Studio 就完事关键在 WDK 版本、平台架构与符号路径闭环NDIS6 驱动开发对工具链极其敏感。微软自 Windows 10 1809 起强制要求使用 WDK 10 VS2019或 VS2022组合且 WDK 版本必须与目标系统内核版本严格匹配——例如为 Windows 11 22H2Build 22621开发驱动必须用 WDK 22621否则NdisMSetAttributesEx会返回NDIS_STATUS_NOT_SUPPORTED即使编译通过也无法加载。常见误区是下载最新 WDK如 23H2却在 Windows 10 21H2 上测试导致NdisOpenAdapterEx失败且日志无明确提示。2.1 WDK 与 Visual Studio 的绑定安装必须用“WDK 安装向导”而非独立安装微软已弃用独立 WDK 安装包。正确做法是下载Visual Studio 2022 Community至少 17.4 版本安装时勾选 “C 桌面开发” “Windows 10/11 SDK”单独下载对应目标系统的WDK ISO例如wdk_22621.1638.iso挂载后运行Installers\wdksetup.exe安装向导会自动检测已安装的 VS2022 实例并将 WDK 组件注入其项目模板中——这是关键若跳过此步VS 新建项目时将看不到 “Kernel Mode Driver (KMDF)” 或 “NDIS Miniport Driver” 模板。提示WDK 安装后C:\Program Files (x86)\Windows Kits\10\Include\wdf和C:\Program Files (x86)\Windows Kits\10\Include\ndis必须存在且非空。若缺失ndis.h或ndisguid.h说明 WDK 未正确集成到 VS。2.2 创建最小 NDIS6 Miniport 驱动工程从模板出发删掉所有“高级功能”新建项目 → “Kernel Mode Driver (KMDF)” → 选择 “NDIS Miniport Driver” 模板注意不是 “WDM Driver” 或 “UMDF”。该模板默认生成支持 NDIS6.30 的完整框架但包含大量冗余代码如 OID 查询处理、电源管理、QoS 支持。我们只保留最核心四要素DriverEntry注册驱动对象MiniportInitializeEx初始化适配器、分配资源MiniportHaltEx释放资源MiniportSendNetBufferLists发送数据本节暂留空实现。其余如MiniportOidRequest,MiniportCheckForHangEx,MiniportResetEx全部注释掉并在NDIS_MINIPORT_DRIVER_CHARACTERISTICS结构体中将对应函数指针置为NULL。这是避免早期蓝屏的最有效手段——NDIS6 要求所有注册的回调函数必须可执行哪怕只是return NDIS_STATUS_SUCCESS;否则NdisMRegisterAdapterEx直接失败。// Miniport.c —— 最小化初始化入口 NDIS_STATUS MiniportInitializeEx( _In_ NDIS_HANDLE MiniportAdapterHandle, _In_ NDIS_HANDLE MiniportDriverContext, _In_ PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters ) { PMP_ADAPTER adapter NULL; // 1. 分配 Adapter 结构体内存必须用 NdisAllocateMemoryWithTagPriority adapter NdisAllocateMemoryWithTagPriority( MiniportAdapterHandle, sizeof(MP_ADAPTER), ADPM, // Tag: MPAD little-endian NormalPoolPriority ); if (!adapter) { return NDIS_STATUS_RESOURCES; } // 2. 初始化关键字段必须设置 MiniportAdapterHandle 和 DriverContext adapter-MiniportAdapterHandle MiniportAdapterHandle; adapter-DriverContext MiniportDriverContext; // 3. 设置 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES必需 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES genAttr {0}; genAttr.Header.Type NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; genAttr.Header.Size sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); genAttr.Header.Revision NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2; genAttr.MediaType NdisMedium802_3; // 以太网 genAttr.PhysicalMediumType NdisPhysicalMediumUnspecified; genAttr.MaxXmitLinkSpeed 1000000000ULL; // 1 Gbps genAttr.XmitLinkSpeed 1000000000ULL; genAttr.MaxRcvLinkSpeed 1000000000ULL; genAttr.RcvLinkSpeed 1000000000ULL; genAttr.LookaheadSize 128; // 关键影响 NBL 接收缓冲区大小 genAttr.MaximumFrameSize 1514; // MTU Ethernet header genAttr.MinimumFrameSize 60; genAttr.MaxTotalBufferSize 0x200000; // 2MB // 4. 注册通用属性此步失败 驱动无法绑定到网络栈 NDIS_STATUS status NdisMSetMiniportAttributes( MiniportAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)genAttr ); if (status ! NDIS_STATUS_SUCCESS) { NdisFreeMemory(adapter, sizeof(MP_ADAPTER), 0); return status; } // 5. 将 Adapter 指针存入 MiniportAdapterHandle 的上下文供后续回调使用 NdisSetMiniportAdapterInstanceContext(MiniportAdapterHandle, adapter); return NDIS_STATUS_SUCCESS; }参数说明ADPM是内存 Tag用于 Windbg 中!poolfind ADPM快速定位泄漏LookaheadSize 128表示 NDIS 在接收前只预读 128 字节判断帧头过小会导致 TCP/IP 栈丢包过大增加延迟MaximumFrameSize 1514必须与物理网卡能力一致若设为 9000Jumbo Frame但硬件不支持NdisMIndicateReceiveNetBufferLists会静默失败MaxTotalBufferSize是 NDIS 为该 Miniport 分配的总接收缓冲区内存上限单位字节建议设为 2MB 起步后续根据吞吐量调优。2.3 编译与签名inf2cat不是可选项而是加载前提NDIS6 驱动在 Windows 10/11 上默认启用驱动强制签名Driver Signature Enforcement, DSE。未签名驱动加载会触发STATUS_INVALID_IMAGE_HASH错误。签名流程如下生成.inf文件VS 模板已生成ndis6miniport.inf修改其中CatalogFile行指向ndis6miniport.cat打开 “Windows Driver Kit Build Environment” 命令行非普通 CMD运行inf2cat /driver:C:\path\to\driver /os:10_X64 /verbose生成.cat文件 4. 使用微软测试证书签名仅限测试环境makecert -r -pe -ss PrivateCertStore -n CNTestRoot TestRoot.cer certutil -user -addstore Root TestRoot.cer signtool sign /v /s PrivateCertStore /n TestRoot /t http://timestamp.digicert.com ndis6miniport.sys signtool sign /v /s PrivateCertStore /n TestRoot /t http://timestamp.digicert.com ndis6miniport.cat注意/os:10_X64必须与目标系统架构一致10_X64表示 Windows 10/11 x64若为 ARM64 则用10_ARM64。错误的 OS 参数会导致.cat文件不被识别。3. 加载与调试用pnputil替代设备管理器用kd抓取NdisMRegisterAdapterEx失败根因NDIS6 驱动不能像普通软件一样双击安装。必须通过命令行工具注入 PnP 数据库并触发内核加载。设备管理器右键“更新驱动”只会报错“找不到合适驱动”因为它不解析.inf中的NdisDeviceID匹配逻辑。3.1 用pnputil注册并安装驱动三步不可省略# 1. 添加驱动包到驱动存储Driver Store pnputil /add-driver ndis6miniport.inf /install # 2. 查看已添加驱动列表确认 Published Name如 oem12.inf pnputil /enum-drivers # 3. 强制安装到指定硬件 ID关键必须匹配 INF 中的 NdisDeviceID pnputil /install-driver ndis6miniport.inf /forceINF 文件中必须定义NdisDeviceID例如[Manufacturer] %VendorName% Standard, NTamd64 [Standard.NTamd64] %DeviceDesc% ndis6miniport.ndi, PCI\VEN_8086DEV_100ESUBSYS_00000000REV_03 [ndis6miniport.ndi] ...其中PCI\VEN_8086DEV_100E...是你的虚拟或物理网卡硬件 ID可通过devmgmt.msc→ 网卡属性 → “详细信息” → “硬件 ID” 获取。若 INF 中 ID 与实际设备不匹配pnputil会成功注册但设备管理器显示“未启用”且无任何错误提示。3.2 启动内核调试器kd定位NdisMRegisterAdapterEx返回NDIS_STATUS_FAILURE的真实原因NDIS6 初始化失败时DriverEntry返回STATUS_SUCCESS但MiniportInitializeEx从未被调用——这说明NdisMRegisterAdapterEx在驱动注册阶段就失败了。此时事件查看器几乎无日志唯一可靠方式是内核调试。在测试机启用内核调试bcdedit /debug onbcdedit /dbgsettings serial debugport:1 baudrate:115200主机用 WinDbg Preview 连接串口加载驱动前在kd中设置断点bu ndis!NdisMRegisterAdapterEx g执行pnputil /install-driver ...断点命中后查看寄存器和堆栈r rax # 返回值0 表示成功非 0 为错误码 !ndiskd.adapters # 查看当前 NDIS 适配器状态 !ndiskd.miniports # 查看 Miniport 注册状态常见失败码及含义返回值十六进制含义典型原因0xC000000DSTATUS_INVALID_PARAMETERNDIS_MINIPORT_DRIVER_CHARACTERISTICS中MajorNdisVersion设为 6但MinorNdisVersion未设为 30NDIS6.30或更高0xC0000022STATUS_ACCESS_DENIED驱动未签名且测试机未禁用 DSEbcdedit /set testsigning on0xC000009ASTATUS_INSUFFICIENT_RESOURCESNdisAllocateMemoryWithTagPriority分配失败通常因NormalPoolPriority在 IRQL DISPATCH_LEVEL 时被拒绝注意NdisMRegisterAdapterEx必须在PASSIVE_LEVELIRQL 下调用。若在DriverEntry中直接调用此时 IRQL 为PASSIVE_LEVEL没问题但若在MiniportInitializeEx中再次调用则必然失败——因为MiniportInitializeEx运行在DISPATCH_LEVEL。3.3 验证驱动是否真正绑定检查NdisMIndicateStatusEx是否被调用NDIS6 驱动加载成功 ≠ 绑定成功。必须看到NdisMIndicateStatusEx被调用且传入NET_IF_MEDIA_CONNECT_STATE_CONNECTED才表示 NDIS 栈已认可该 Miniport 并准备收发数据。在MiniportInitializeEx末尾添加// 模拟链路就绪实际应由硬件中断触发 NDIS_LINK_STATE linkState {0}; linkState.Header.Type NDIS_OBJECT_TYPE_DEFAULT; linkState.Header.Size sizeof(NDIS_LINK_STATE); linkState.Header.Revision NDIS_LINK_STATE_REVISION_1; linkState.MediaConnectState MediaConnectStateConnected; linkState.XmitLinkSpeed 1000000000ULL; linkState.RcvLinkSpeed 1000000000ULL; NdisMIndicateStatusEx(MiniportAdapterHandle, linkState);然后在kd中设置断点bu ndis!NdisMIndicateStatusEx g若断点命中且rcx第一个参数为有效MiniportAdapterHandle说明绑定链路已通。此时ipconfig /all应能看到新网卡名称为 INF 中DeviceDesc且状态为“已启用”。4. 避坑NDIS6 Miniport 开发中 5 个让 90% 工程师重启三次的硬核陷阱NDIS6 文档晦涩、错误码模糊、调试工具链复杂新手常陷入“编译通过→安装成功→设备管理器显示正常→但 ping 不通”的死循环。以下是我在三个真实项目虚拟交换机、内核级抓包、硬件加速转发中踩出的血泪经验按发生频率排序4.1 现象MiniportInitializeEx从未被调用设备管理器显示“该设备运转正常”但无网络流量原因INF 文件中NdisDeviceID与实际硬件 ID 不匹配且CopyFiles节未正确复制.sys文件到System32\drivers解决运行pnputil /enum-drivers查看Published Name记下oemXX.inf进入C:\Windows\System32\DriverStore\FileRepository\oemXX.inf_XXXXX\确认ndis6miniport.sys存在且时间戳最新若不存在检查 INF 的[SourceDisksFiles]节是否包含[SourceDisksFiles] ndis6miniport.sys1,,并确保ndis6miniport.sys与 INF 同目录。4.2 现象NdisMIndicateReceiveNetBufferLists调用后上层协议栈TCP/IP不处理数据包Wireshark 抓不到入站帧原因NdisMIndicateReceiveNetBufferLists中NetBufferList的NetBuffer链表结构损坏或NBL_FLAGS_IS_IMMEDIATE未置位解决必须调用NdisAdvanceNetBufferListDataStart将NetBuffer的CurrentMdl指向有效内存必须设置NET_BUFFER_LIST_INFO(Nbl, Ipv4ChecksumSucceeded) TRUE即使未校验否则 TCP/IP 栈丢弃关键在NdisMIndicateReceiveNetBufferLists前调用NdisGetFirstNetBufferFromNetBufferList(Nbl)获取首个NetBuffer再用NET_BUFFER_DATA_LENGTH(nb)验证长度 ≥ 14Ethernet Header。4.3 现象驱动加载后系统响应迟缓CPU 占用率 100%!thread显示大量ndis!NdisIMCompleteRequest线程阻塞原因MiniportReturnNetBufferLists中未调用NdisFreeNetBufferList导致 NBL 内存泄漏NDIS 内部队列积压解决每个NdisMIndicateReceiveNetBufferLists对应的NBL必须在上层协议栈处理完毕后由 Miniport 的MiniportReturnNetBufferLists回调中释放释放前必须调用NdisResetNetBufferList(Nbl)清除所有NET_BUFFER_LIST_INFO字段否则下次复用时残留标志引发异常。4.4 现象MiniportSendNetBufferLists返回NDIS_STATUS_PENDING但MiniportSendComplete从未被调用原因NdisMSendNetBufferListsComplete调用时传入的NBL地址与MiniportSendNetBufferLists接收的不一致常见于多线程并发发送时未加锁解决在MiniportSendNetBufferLists中对每个NBL调用NdisRetreatNetBufferListDataStart后立即用NdisQueryPacketGroupInfo获取唯一标识在MiniportSendComplete中用NdisQueryPacketGroupInfo再次查询比对标识符更稳妥做法在MiniportSendNetBufferLists中为每个NBL分配私有上下文NdisAllocateCloneNetBufferList将上下文指针存入NBL的MiniportReserved数组。4.5 现象驱动在 Windows 11 22H2 上蓝屏错误码DRIVER_IRQL_NOT_LESS_OR_EQUAL (0x000000D1)崩溃地址指向ndis!ndisMIndicateStatusEx原因MiniportHaltEx中调用了NdisFreeMemory释放仍在被 NDIS 引用的内存如NdisAllocateMemoryWithTagPriority分配的MP_ADAPTER解决MiniportHaltEx中只能释放 Miniport 自己申请的资源如 DMA buffer、中断对象MP_ADAPTER结构体必须在MiniportShutdownExNDIS6.30 新增回调中释放且必须先调用NdisMDeregisterAdapterExMiniportShutdownEx运行在PASSIVE_LEVEL是唯一安全释放MiniportAdapterHandle相关内存的时机。5. 发送与接收实战用NdisMIndicateReceiveNetBufferLists模拟 ARP 响应验证端到端链路光让驱动加载成功只是起点。真正的价值在于能否让上层协议栈把你的 Miniport 当作真实网卡收发标准以太网帧。本节用最简方式——模拟 ARP 响应——验证接收与发送闭环。不依赖硬件纯软件构造帧直击 NDIS6 数据路径核心。5.1 构造一个合法 ARP Reply 帧字段必须全对否则tcpip.sys直接丢弃NDIS6 对接收帧合法性校验极严。以下 C 代码在MiniportInitializeEx后构造一个 ARP Reply目标 IP192.168.1.100MAC00-11-22-33-44-55// 构造 ARP Reply 帧以太网 ARP typedef struct _ETHERNET_HEADER { UCHAR DstMac[6]; UCHAR SrcMac[6]; USHORT Type; // 0x0806 for ARP } ETHERNET_HEADER, *PETHERNET_HEADER; typedef struct _ARP_HEADER { USHORT HardwareType; // 0x0001 (Ethernet) USHORT ProtocolType; // 0x0800 (IPv4) UCHAR HardwareSize; // 6 UCHAR ProtocolSize; // 4 USHORT OpCode; // 0x0002 (ARP Reply) UCHAR SenderMac[6]; // 本机 MAC ULONG SenderIp; // 192.168.1.100 UCHAR TargetMac[6]; // 请求方 MAC ULONG TargetIp; // 请求方 IP } ARP_HEADER, *PARP_HEADER; VOID ConstructArpReply(PMP_ADAPTER adapter) { // 1. 分配 64 字节内存Ethernet 14 ARP 28 42向上对齐 PUCHAR frame NdisAllocateMemoryWithTagPriority( adapter-MiniportAdapterHandle, 64, ARPF, NormalPoolPriority ); if (!frame) return; // 2. 填充 Ethernet Header RtlCopyMemory(frame, \xFF\xFF\xFF\xFF\xFF\xFF, 6); // Broadcast Dst RtlCopyMemory(frame 6, adapter-CurrentAddress, 6); // Src MAC *(PUSHORT)(frame 12) htons(0x0806); // ARP Type // 3. 填充 ARP Header PARP_HEADER arp (PARP_HEADER)(frame 14); arp-HardwareType htons(0x0001); arp-ProtocolType htons(0x0800); arp-HardwareSize 6; arp-ProtocolSize 4; arp-OpCode htons(0x0002); RtlCopyMemory(arp-SenderMac, adapter-CurrentAddress, 6); arp-SenderIp htonl(0xC0A80164); // 192.168.1.100 RtlZeroMemory(arp-TargetMac, 6); // 由上层填充 arp-TargetIp htonl(0xC0A80101); // 192.168.1.1 // 4. 构建 NetBufferList关键 PNET_BUFFER_LIST nbl NdisAllocateNetBufferAndNetBufferList( adapter-NblPoolHandle, NULL, 0, 64, frame, 0 ); if (!nbl) { NdisFreeMemory(frame, 64, 0); return; } // 5. 设置 NBL 标志必须 NET_BUFFER_LIST_SET_NET_BUFFER_LIST_INFO(nbl, NetBufferListFrameType, (PVOID)(ULONG_PTR)0x0806); NET_BUFFER_LIST_SET_NET_BUFFER_LIST_INFO(nbl, NetBufferListStatus, NDIS_STATUS_SUCCESS); NET_BUFFER_LIST_SET_NET_BUFFER_LIST_INFO(nbl, NetBufferListFlags, NBL_FLAGS_IS_IMMEDIATE); // 6. 指示接收此时 tcpip.sys 会解析并响应 NdisMIndicateReceiveNetBufferLists( adapter-MiniportAdapterHandle, nbl, 0, 1, 0 ); }关键点说明NdisAllocateNetBufferAndNetBufferList必须使用驱动创建的NBL内存池adapter-NblPoolHandle不能用全局池NetBufferListFrameType必须设为0x0806ARP否则tcpip.sys不识别NBL_FLAGS_IS_IMMEDIATE表示该帧需立即处理避免排队延迟NdisMIndicateReceiveNetBufferLists第四个参数NumberOfNetBufferLists必须为1即使只传一个 NBL。5.2 发送 ARP Request 触发响应用NdisMSendNetBufferLists发起请求形成闭环要验证发送路径需主动发 ARP Request。此处复用上述帧结构仅修改OpCode和 MAC 地址// 在 MiniportSendNetBufferLists 中简化版 VOID MiniportSendNetBufferLists( _In_ NDIS_HANDLE MiniportAdapterContext, _In_ PNET_BUFFER_LIST NetBufferLists, _In_ NDIS_PORT_NUMBER PortNumber, _In_ ULONG SendFlags ) { PMP_ADAPTER adapter (PMP_ADAPTER)MiniportAdapterContext; PNET_BUFFER nb NdisGetFirstNetBufferFromNetBufferList(NetBufferLists); ULONG length NET_BUFFER_DATA_LENGTH(nb); // 检查是否为 ARP Request目的 MAC 全 FOpCode1 PUCHAR data MmGetSystemAddressForMdlSafe(NET_BUFFER_CURRENT_MDL(nb), NormalPagePriority); if (data length 42) { if (*(PUSHORT)(data 12) htons(0x0806)) { // ARP PARP_HEADER arp (PARP_HEADER)(data 14); if (arp-OpCode htons(0x0001)) { // Request // 构造 Reply 并指示接收模拟本机响应 ConstructArpReply(adapter); } } } // 调用完成回调模拟发送成功 NdisMSendNetBufferListsComplete( adapter-MiniportAdapterHandle, NetBufferLists, 0 ); }验证方法在另一台机器执行arp -d *清空缓存执行ping 192.168.1.100观察本机 Wireshark应捕获到ARP Request来自 ping 机→ARP Reply由你的驱动构造并指示→ICMP Echo Request→ICMP Echo Reply若看到ARP Reply但无后续 ICMP说明MiniportSendNetBufferLists中未正确处理ICMP Echo Request需扩展逻辑。5.3 性能调优NdisMIndicateReceiveNetBufferLists的批处理与 IRQL 控制生产环境中单帧指示效率低下。NDIS6 支持批量指示NumberOfNetBufferLists 1但必须满足所有NBL必须属于同一PortNumber所有NBL的NetBuffer必须在相同 IRQL 下分配即全部在DISPATCH_LEVEL批量大小建议 32~64过大导致NdisMIndicateReceiveNetBufferLists调用时间过长影响实时性。// 批量指示示例伪代码 VOID BatchIndicate(PMP_ADAPTER adapter, PNET_BUFFER_LIST* nblArray, ULONG count) { // 确保所有 NBL 在同一 IRQLDISPATCH_LEVEL KIRQL oldIrql; KeRaiseIrql(DISPATCH_LEVEL, oldIrql); NdisMIndicateReceiveNetBufferLists( adapter-MiniportAdapterHandle, nblArray[0], // 第一个 NBL 0, // Default port count, // 批量数 0 // Flags ); KeLowerIrql(oldIrql); }注意KeRaiseIrql(DISPATCH_LEVEL, ...)是必须的。NDIS6 要求NdisMIndicateReceiveNetBufferLists在DISPATCH_LEVEL或更高 IRQL 下调用否则触发DRIVER_VERIFIER_DETECTED_VIOLATION。这是文档极少提及但实际开发中高频翻车点。我习惯在MiniportInitializeEx中预分配 1024 个NBL到环形缓冲区并用ExInterlockedPushEntrySList在 DPC 中快速入队再由MiniportInterruptDpc批量指示——这套模式在 10Gbps 虚拟交换机中稳定跑满线速。希望帮到你。本文还有配套的精品资源点击获取
返回列表