NDIS 库 (ndis.sys) 驱动程序分析
目录
1. 概述
NDIS (Network Driver Interface Specification) 是微软定义的网络驱动接口规范,是 Windows 网络体系结构的核心组件。ReactOS 的 NDIS 库 (ndis.sys) 是一个遵循 NDIS 5.1 规范的实现,位于 d:\\reactos\\drivers\\network\\ndis\\ 目录下。
1.1 设计思想与架构哲学
NDIS 的设计核心思想是分层抽象 + 集中调度。
在传统的网络驱动实现中,协议栈(如 TCP/IP)需要直接与硬件驱动交互,这要求每个协议驱动都必须了解每种网卡驱动的内部细节,导致严重的耦合问题。NDIS 的解决办法是引入一个中间抽象层——即 ndis.sys 本身——位于协议驱动和微型端口驱动之间,承担以下核心角色:
- 调度器角色:管理所有数据包的发送/接收序列化,通过工作项队列避免竞态条件
- 绑定器角色:维护协议→适配器、适配器→协议的动态绑定关系,支持即插即用热插拔
- 适配器角色:为上层的协议驱动和下层的微型端口驱动提供统一的函数调用约定,使两边都不需要知道对方的具体实现细节
这种设计的核心价值在于:微型端口驱动只需要实现 10-15 个标准回调函数(Init/Halt/Send/SendPackets/QueryInfo/SetInfo/Reset/ISR/HandleInterrupt/EnableInterrupt/DisableInterrupt/TransferData/ReturnPacket/CheckForHang),而协议驱动也只需要实现类似数量的回调(BindAdapter/UnbindAdapter/SendComplete/ReceiveHandler/StatusHandler/PnPEventHandler 等)。所有复杂的调度、同步、绑定管理、PnP 协调都由 NDIS 库统一处理。
1.2 主要功能
- 为协议驱动(如 TCP/IP)和微型端口驱动(如 e1000、rtl8139)提供标准化的通信接口
- 管理网络数据包的发送和接收流程
- 协调即插即用 (PnP) 事件和电源管理事件
- 提供配置管理(注册表操作)
- 提供内存管理(包括 DMA 共享内存)
- 提供计时器和同步原语
- 通过工作项队列实现序列化和异步调度
1.3 与 Linux 网络驱动架构的差异
ReactOS 的 TCP/IP 协议栈 (tcpip.sys) 实际上是从 Linux 内核 2.4.20 移植而来(见 [tcpcore.h](file:///d:/reactos/drivers/network/tcpip/include/tcpcore.h) 的注释 Ported from linux kernel 2.4.20),但在 NDIS 框架下运行时,两者呈现出截然不同的设计哲学。
| 核心架构 | 三层严格分层:协议驱动 → NDIS 库 → 微型端口驱动。NDIS 作为独立的内核模块存在,承担调度和管理职责 | 两层轻量架构:协议栈直接调用 net_device_ops 中的函数指针,没有独立的"中间库层",驱动模型由内核统一框架提供 |
| 数据包表示 | NDIS_PACKET + NDIS_BUFFER (MDL):基于 Windows MDL (Memory Descriptor List) 机制,包描述符和数据分离,通过 MDL 链支持 Scatter/Gather I/O | struct sk_buff:统一的缓冲区结构,使用 head/data/tail/end 四个指针灵活管理协议头空间,支持克隆 (skb_clone)、共享、分片 (skb_shinfo),内联了全套操作函数 |
| 发送模型 | 异步回调驱动:MiniportSend[Packets] 返回 NDIS_STATUS_PENDING 表示异步,发送完成后调用 NdisMSendComplete() 回调协议。NDIS 库负责任何必要的序列化和排队 | 同步+流量控制:dev->hard_start_xmit(skb) 同步发送,返回 NETDEV_TX_OK 或 NETDEV_TX_BUSY。驱动通过 netif_stop_queue()/netif_wake_queue() 控制上层是否继续发送 |
| 接收模型 | 推模式 (Push):微型端口通过 NdisMIndicateReceivePacket 将数据推送给 NDIS,NDIS 遍历绑定协议列表逐层推送。有传统 ReceiveHandler 和新式 ReceivePacketHandler 两种方式 | NAPI 轮询 (Poll)(Linux 2.6+):中断上半部关闭中断,注册 NAPI 结构到轮询列表;softIRQ 上下文中通过 poll(napi, budget) 批量轮询接收,减少高负载下的中断开销 |
| 协议绑定 | NDIS 集中管理:NDIS 维护全局 ProtocolListHead 和每个适配器的 ProtocolListHead,通过 ndisBindMiniportsToProtocol() 从注册表读取绑定配置。支持多个协议绑定到同一适配器 | 内核统一管理:通过 dev_add_pack() 注册 packet_type 到全局 ptype_all/ptype_base 哈希表,内核网络栈在接收时根据协议类型分发给不同处理函数 |
| 中断处理 | ISR + DPC 两阶段:MiniportISR(在 DIRQL 上运行,仅判断中断归属和是否需要 DPC)→ HandleDeferredProcessing DPC(在 DISPATCH_LEVEL 上运行,调用 MiniportHandleInterrupt + MiniportEnableInterrupt) | hardIRQ + softIRQ 两阶段:硬中断(仅做最小处理,如获取数据)→ softIRQ(NET_RX_SOFTIRQ/NET_TX_SOFTIRQ 中做实际协议处理,不在驱动中完成,而是交给内核协议栈) |
| 序列化模型 | 可配置序列化:通过 NDIS_ATTRIBUTE_DESERIALIZE 标志位区分串行化/反串行化两种模式。串行化模式下 NDIS 保证每次只有一个请求到达微型端口;反串行化模式下驱动自行管理并发 | 驱动自行管理:内核不提供统一的序列化机制,驱动使用自旋锁、RCU、per-CPU 变量等标准内核同步机制自行管理并发。ndo_start_xmit 可能在多个 CPU 上同时调用 |
| 配置/OID 管理 | 统一的 OID 机制:所有查询/设置操作通过 MiniportQueryInformation/MiniportSetInformation 一个回调入口,通过 NDIS_OID 枚举值(如 OID_GEN_MAC_OPTIONS、OID_802_3_CURRENT_ADDRESS)区分操作类型。NDIS 提供 NdisReadConfiguration、NdisOpenConfiguration 等注册表封装 | 分散的接口:通过多个 net_device_ops 函数实现(ndo_do_ioctl、ndo_get_stats、ndo_set_mac_address 等),或通过 ethtool_ops 实现。没有统一的 OID 枚举体系 |
| PnP/电源管理 | NDIS 内置支持:NDIS 通过 NdisIAddDevice(创建设备)、NdisIPnPStartDevice(启动设备,调用 MiniportInitialize)、NdisIPnPStopDevice(停止设备,调用 MiniportHalt)完整地封装了 PnP 流程。电源事件通过 NetEventSetPower/NetEventQueryPower PnP 事件通知协议 | 内核驱动模型:使用标准的 struct device_driver 模型,probe/remove 函数由内核在总线枚举时调用,电源管理通过 dev_pm_ops 实现 |
| DMA 管理 | NDIS 封装:NdisMInitializeScatterGatherDma 初始化 DMA 通道,NdisMAllocateSharedMemory 分配共享内存,GetScatterGatherList/PutScatterGatherList 管理 Scatter/Gather 列表。NDIS 在内部分配 DMA_ADAPTER 和 DMA_OPERATIONS | 通用 DMA API:dma_alloc_coherent()、dma_map_single()、dma_map_sg() 等。在 PCI 驱动中使用 pci_alloc_consistent() 等封装。由内核通用 DMA 层统一管理 |
| 兼容性 | NDIS 版本化兼容:通过编译宏 (NDIS40/NDIS50/NDIS51) 和不同大小的 MiniportCharacteristics 结构支持 NDIS 3.0/4.0/5.0/5.1 的二进制兼容。30stubs.c、40stubs.c、50stubs.c 提供桩函数 | 内核版本绑定:驱动必须针对特定内核版本编译,net_device_ops 结构在不同内核版本间有较大差异,不保证二进制兼容性 |
| 工作项延迟处理 | NDIS 工作项队列:MiniQueueWorkItem + MiniportWorker 实现串行化的工作项调度,支持 NdisWorkItemSend、NdisWorkItemRequest、NdisWorkItemResetRequested 等工作类型,通过内核 IoQueueWorkItem 实现 | workqueue/tasklet:Linux 内核提供通用的 work_struct + schedule_work() 和 tasklet 机制,驱动根据自己的需要使用这些通用机制,没有 NDIS 这样专门针对网络驱动的专用工作项队列 |
1.4 NDIS 这样设计的优缺点
优点:
缺点:
1.5 支持的 NDIS 版本
通过构建宏定义,支持 NDIS 3.0/4.0/5.0/5.1 的兼容性:
-DNDIS_WRAPPER
-DNDIS51
-DNDIS51_MINIPORT
-DNDIS_MINIPORT_DRIVER
-DNDIS_LEGACY_DRIVER=1
-DNDIS_LEGACY_MINIPORT=1
-DNDIS_LEGACY_PROTOCOL=1
2. 框架结构
2.1 分层架构
NDIS 采用标准的三层网络驱动架构:
+————————————–+
| 协议驱动 (Protocol) |
| tcpip.sys, ppp.sys, etc. |
+————————————–+
| NdisSend / NdisReceive etc.
v
+————————————–+
| NDIS 库 (ndis.sys) |
| – 数据包调度 |
| – 协议/微型端口绑定管理 |
| – 配置管理 |
| – 中断处理 |
| – PnP/电源管理 |
+————————————–+
| MiniportXxx callbacks
v
+————————————–+
| 微型端口驱动 (Miniport) |
| e1000.sys, rtl8139.sys, etc. |
+————————————–+
2.2 模块组织
NDIS 库由以下源文件组成:
| main.c | 驱动入口点 DriverEntry,初始化全局列表和锁 |
| miniport.c | 微型端口支持(初始化、发送/接收完成、请求处理、工作项队列、PnP 事件处理) |
| protocol.c | 协议驱动支持(协议注册、适配器打开/关闭、发送/请求转发) |
| buffer.c | 数据包/缓冲区管理(NDIS_PACKET、NDIS_BUFFER 操作) |
| config.c | 注册表配置读写(NdisOpenConfiguration、NdisReadConfiguration 等) |
| memory.c | 内存管理(含 DMA 共享内存分配/释放) |
| io.c | 中断服务例程 (ISR) 和 DPC 处理 |
| hardware.c | PCI 配置空间读写、资源分配 |
| control.c | 读写锁同步 |
| efilter.c | 以太网帧过滤 |
| object.c | NDIS 6.0 通用对象接口 |
| workitem.c | NDIS 6.0 工作项接口 |
| time.c | 计时器管理 |
| string.c | 字符串操作 |
| misc.c | 杂项(互锁操作、字符串比较) |
| cl.c | 面向连接客户端 |
| cm.c | 呼叫管理器 |
| co.c | 面向连接支持 |
| 30stubs.c | NDIS 3.0 兼容性桩函数 |
| 40stubs.c | NDIS 4.0 兼容性桩函数 |
| 50stubs.c | NDIS 5.0 兼容性桩函数 |
2.3 关键调用约定
协议驱动 -> NdisSend() -> ProSend() -> proSendPacketToMiniport() -> MiniportSend[Packets]Handler
协议驱动 -> NdisRequest() -> ProRequest() -> MiniDoRequest() -> MiniportQueryInfo/SetInfoHandler
微型端口 -> NdisMSendComplete() -> MiniSendComplete() -> ProtocolSendCompleteHandler
微型端口 -> NdisMIndicateStatus() -> MiniStatus() -> ProtocolStatusHandler
3. 核心数据结构
3.1 逻辑适配器 (LOGICAL_ADAPTER)
定义在 [miniport.h](file:///d:/reactos/drivers/network/ndis/include/miniport.h#L87-L99):
typedef struct _LOGICAL_ADAPTER
{
NDIS_MINIPORT_BLOCK NdisMiniportBlock; // NDIS 定义的标准字段
PNDIS_MINIPORT_WORK_ITEM WorkQueueHead; // 工作队列头
PNDIS_MINIPORT_WORK_ITEM WorkQueueTail; // 工作队列尾
LIST_ENTRY ListEntry; // 全局适配器链表
LIST_ENTRY MiniportListEntry; // 微型端口驱动链表的入口
LIST_ENTRY ProtocolListHead; // 绑定到此适配器的协议链表
ULONG MediumHeaderSize; // 介质头大小(如 Ethernet=14)
HARDWARE_ADDRESS Address; // 硬件地址 (MAC)
ULONG AddressLength; // 硬件地址长度
PMINIPORT_BUGCHECK_CONTEXT BugcheckContext; // 关机回调上下文
} LOGICAL_ADAPTER, *PLOGICAL_ADAPTER;
3.2 微型端口驱动块 (NDIS_M_DRIVER_BLOCK)
typedef struct _NDIS_M_DRIVER_BLOCK {
LIST_ENTRY ListEntry; // 全局链表入口
KSPIN_LOCK Lock; // 保护自旋锁
NDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics; // 微型端口特性(函数指针表)
WORK_QUEUE_ITEM WorkItem; // 工作项
PDRIVER_OBJECT DriverObject; // 驱动对象
LIST_ENTRY DeviceList; // 该驱动创建的适配器列表
PUNICODE_STRING RegistryPath; // 注册表路径
} NDIS_M_DRIVER_BLOCK;
3.3 协议绑定 (PROTOCOL_BINDING)
定义在 [protocol.h](file:///d:/reactos/drivers/network/ndis/include/protocol.h#L10-L16):
typedef struct _PROTOCOL_BINDING {
LIST_ENTRY ListEntry; // 全局链表入口
KSPIN_LOCK Lock; // 保护自旋锁
NDIS_PROTOCOL_CHARACTERISTICS Chars; // 协议特性(函数指针表)
WORK_QUEUE_ITEM WorkItem; // 工作项
LIST_ENTRY AdapterListHead; // 已绑定的适配器列表
} PROTOCOL_BINDING, *PPROTOCOL_BINDING;
3.4 适配器绑定 (ADAPTER_BINDING)
typedef struct _ADAPTER_BINDING {
NDIS_OPEN_BLOCK NdisOpenBlock; // NDIS 定义的标准字段
LIST_ENTRY ListEntry; // 全局链表入口
LIST_ENTRY ProtocolListEntry; // 协议绑定的适配器链表入口
LIST_ENTRY AdapterListEntry; // 逻辑适配器的协议链表入口
KSPIN_LOCK Lock; // 保护自旋锁
PPROTOCOL_BINDING ProtocolBinding; // 对应的协议
PLOGICAL_ADAPTER Adapter; // 对应的适配器
} ADAPTER_BINDING, *PADAPTER_BINDING;
3.5 工作项 (NDIS_MINIPORT_WORK_ITEM)
支持的工作项类型:
| NdisWorkItemSend | 发送数据包 |
| NdisWorkItemSendLoopback | 回环发送 |
| NdisWorkItemReturnPackets | 归还数据包 |
| NdisWorkItemResetRequested | 适配器重置 |
| NdisWorkItemResetInProgress | 重置进行中 |
| NdisWorkItemMiniportCallback | 微型端口回调 |
| NdisWorkItemRequest | 查询/设置请求 |
| NdisMaxWorkItems | 用于遍历所有类型 |
3.6 全局链表结构
全局协议列表 (ProtocolListHead)
↓
+——————-+
| PROTOCOL_BINDING | —- AdapterListHead –> [ADAPTER_BINDING] -> [ADAPTER_BINDING]
+——————-+
全局微型端口列表 (MiniportListHead)
↓
+——————-+
| NDIS_M_DRIVER_BLOCK| —- DeviceList –> [LOGICAL_ADAPTER] -> [LOGICAL_ADAPTER]
+——————-+
全局适配器列表 (AdapterListHead)
↓
+——————-+
| LOGICAL_ADAPTER | —- ProtocolListHead –> [ADAPTER_BINDING] -> [ADAPTER_BINDING]
+——————-+
4. 核心模块分析
4.1 主入口 (main.c)
DriverEntry 函数执行以下初始化:
4.2 微型端口管理 (miniport.c)
这是 NDIS 库中最大的模块,负责:
4.2.1 微型端口注册 (NdisMRegisterMiniport)
- 验证 MiniportCharacteristics 版本(3.0/4.0/5.0/5.1)
- 验证必需的函数指针(Halt, Initialize, Reset 必须提供)
- 复制特性到全局结构
- 注册 AddDevice 回调 (NdisIAddDevice)
- 注册通用 IRP 处理器 (NdisGenericIrpHandler)
4.2.2 PnP 设备管理
设备创建 (NdisIAddDevice):
设备启动 (NdisIPnPStartDevice):
设备停止 (NdisIPnPStopDevice):
4.2.3 工作项队列
NDIS 使用工作项队列来序列化对微型端口的操作:
MiniQueueWorkItem() → 入队(尾插法)
MiniDequeueWorkItem() → 出队(头删法)
MiniportWorker() → 工作线程处理
MiniWorkItemComplete() → 完成并检查是否有后续工作项
工作类型包括发送、请求、重置等,通过 MiniportWorker 统一调度。
4.3 协议管理 (protocol.c)
4.3.1 协议注册 (NdisRegisterProtocol)
4.3.2 协议-适配器绑定 (ndisBindMiniportsToProtocol)
绑定过程:
4.3.3 适配器打开 (NdisOpenAdapter)
4.4 缓冲区管理 (buffer.c)
NDIS 缓冲区体系基于 MDL (Memory Descriptor List):
NDIS_PACKET
├── Private.Head → NDIS_BUFFER (MDL) → NDIS_BUFFER (MDL) → …
├── Private.Tail → NDIS_BUFFER (MDL)
├── Reserved[0..3] (协议/微型端口保留)
├── WrapperReserved[0..3]
└── 包扩展数据 (NDIS_PACKET_OOB_DATA + NDIS_PACKET_EXTENSION)
关键操作:
- NdisAllocateBuffer → 调用 IoAllocateMdl + MmBuildMdlForNonPagedPool
- NdisAllocatePacketPoolEx → 预分配池,通过空闲链表管理
- CopyBufferChainToBuffer → 遍历 MDL 链复制到连续缓冲区
- CopyPacketToBuffer → 从数据包复制到缓冲区
4.5 中断处理 (io.c)
中断处理分为两个阶段:
硬件中断
↓
MiniportISR() ← ISR 阶段(高 IRQL)
├── InterruptRecognized = TRUE
└── QueueMiniportHandleInterrupt = TRUE
↓
HandleDeferredProcessing() ← DPC 阶段(DISPATCH_LEVEL)
├── MiniportHandleInterrupt()
└── MiniportEnableInterrupt()
4.6 配置管理 (config.c)
NDIS 对注册表的操作提供了资源跟踪机制:
- NdisOpenConfiguration / NdisOpenProtocolConfiguration → 打开注册表键
- NdisReadConfiguration → 读取配置值(支持 Integer/HexInteger/String/MultiString/Binary)
- NdisWriteConfiguration → 写入配置值
- NdisCloseConfiguration → 关闭并释放所有跟踪资源
资源跟踪通过 MINIPORT_CONFIGURATION_CONTEXT 和 MINIPORT_RESOURCE 链表实现。
4.7 以太网过滤 (efilter.c)
当微型端口指示接收到数据时,EthFilterDprIndicateReceive 被调用,它会:
5. 工作流程图
5.1 驱动初始化流程
#mermaid-svg-AENlTMH9UNBwsCkq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AENlTMH9UNBwsCkq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AENlTMH9UNBwsCkq .error-icon{fill:#552222;}#mermaid-svg-AENlTMH9UNBwsCkq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AENlTMH9UNBwsCkq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AENlTMH9UNBwsCkq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AENlTMH9UNBwsCkq .marker.cross{stroke:#333333;}#mermaid-svg-AENlTMH9UNBwsCkq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AENlTMH9UNBwsCkq p{margin:0;}#mermaid-svg-AENlTMH9UNBwsCkq .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AENlTMH9UNBwsCkq .cluster-label text{fill:#333;}#mermaid-svg-AENlTMH9UNBwsCkq .cluster-label span{color:#333;}#mermaid-svg-AENlTMH9UNBwsCkq .cluster-label span p{background-color:transparent;}#mermaid-svg-AENlTMH9UNBwsCkq .label text,#mermaid-svg-AENlTMH9UNBwsCkq span{fill:#333;color:#333;}#mermaid-svg-AENlTMH9UNBwsCkq .node rect,#mermaid-svg-AENlTMH9UNBwsCkq .node circle,#mermaid-svg-AENlTMH9UNBwsCkq .node ellipse,#mermaid-svg-AENlTMH9UNBwsCkq .node polygon,#mermaid-svg-AENlTMH9UNBwsCkq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AENlTMH9UNBwsCkq .rough-node .label text,#mermaid-svg-AENlTMH9UNBwsCkq .node .label text,#mermaid-svg-AENlTMH9UNBwsCkq .image-shape .label,#mermaid-svg-AENlTMH9UNBwsCkq .icon-shape .label{text-anchor:middle;}#mermaid-svg-AENlTMH9UNBwsCkq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AENlTMH9UNBwsCkq .rough-node .label,#mermaid-svg-AENlTMH9UNBwsCkq .node .label,#mermaid-svg-AENlTMH9UNBwsCkq .image-shape .label,#mermaid-svg-AENlTMH9UNBwsCkq .icon-shape .label{text-align:center;}#mermaid-svg-AENlTMH9UNBwsCkq .node.clickable{cursor:pointer;}#mermaid-svg-AENlTMH9UNBwsCkq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AENlTMH9UNBwsCkq .arrowheadPath{fill:#333333;}#mermaid-svg-AENlTMH9UNBwsCkq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AENlTMH9UNBwsCkq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AENlTMH9UNBwsCkq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AENlTMH9UNBwsCkq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AENlTMH9UNBwsCkq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AENlTMH9UNBwsCkq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AENlTMH9UNBwsCkq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AENlTMH9UNBwsCkq .cluster text{fill:#333;}#mermaid-svg-AENlTMH9UNBwsCkq .cluster span{color:#333;}#mermaid-svg-AENlTMH9UNBwsCkq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AENlTMH9UNBwsCkq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AENlTMH9UNBwsCkq rect.text{fill:none;stroke-width:0;}#mermaid-svg-AENlTMH9UNBwsCkq .icon-shape,#mermaid-svg-AENlTMH9UNBwsCkq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AENlTMH9UNBwsCkq .icon-shape p,#mermaid-svg-AENlTMH9UNBwsCkq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AENlTMH9UNBwsCkq .icon-shape .label rect,#mermaid-svg-AENlTMH9UNBwsCkq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AENlTMH9UNBwsCkq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AENlTMH9UNBwsCkq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AENlTMH9UNBwsCkq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
协议驱动注册
PnP 设备启动
微型端口驱动注册
DriverEntry
初始化全局列表和锁
NdisMInitializeWrapper
分配 NDIS_M_DRIVER_BLOCK
保存 DriverObject 和 RegistryPath
加入全局 MiniportListHead
NdisMRegisterMiniport
验证 Characteristics
注册 AddDevice = NdisIAddDevice
注册 MajorFunction = NdisGenericIrpHandler
IRP_MN_START_DEVICE
NdisIPnPStartDevice
加入全局 AdapterListHead
打开注册表读取总线信息
设置内部回调处理器
调用 MiniportInitialize
查询 MAC 能力(OID 查询)
创建以太网过滤器
启动挂起检测计时器
绑定所有协议到本适配器
NdisRegisterProtocol
验证协议版本
分配 PROTOCOL_BINDING
ndisBindMiniportsToProtocol
读取 Bind 注册表值
对每个设备调用 BindAdapterHandler
协议调用 NdisOpenAdapter
创建 ADAPTER_BINDING
加入协议和适配器列表
5.2 数据包发送流程
#mermaid-svg-Qva2PI8ZFsmfbTwT{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Qva2PI8ZFsmfbTwT .error-icon{fill:#552222;}#mermaid-svg-Qva2PI8ZFsmfbTwT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Qva2PI8ZFsmfbTwT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .marker.cross{stroke:#333333;}#mermaid-svg-Qva2PI8ZFsmfbTwT svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Qva2PI8ZFsmfbTwT p{margin:0;}#mermaid-svg-Qva2PI8ZFsmfbTwT .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster-label text{fill:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster-label span{color:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster-label span p{background-color:transparent;}#mermaid-svg-Qva2PI8ZFsmfbTwT .label text,#mermaid-svg-Qva2PI8ZFsmfbTwT span{fill:#333;color:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .node rect,#mermaid-svg-Qva2PI8ZFsmfbTwT .node circle,#mermaid-svg-Qva2PI8ZFsmfbTwT .node ellipse,#mermaid-svg-Qva2PI8ZFsmfbTwT .node polygon,#mermaid-svg-Qva2PI8ZFsmfbTwT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .rough-node .label text,#mermaid-svg-Qva2PI8ZFsmfbTwT .node .label text,#mermaid-svg-Qva2PI8ZFsmfbTwT .image-shape .label,#mermaid-svg-Qva2PI8ZFsmfbTwT .icon-shape .label{text-anchor:middle;}#mermaid-svg-Qva2PI8ZFsmfbTwT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .rough-node .label,#mermaid-svg-Qva2PI8ZFsmfbTwT .node .label,#mermaid-svg-Qva2PI8ZFsmfbTwT .image-shape .label,#mermaid-svg-Qva2PI8ZFsmfbTwT .icon-shape .label{text-align:center;}#mermaid-svg-Qva2PI8ZFsmfbTwT .node.clickable{cursor:pointer;}#mermaid-svg-Qva2PI8ZFsmfbTwT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .arrowheadPath{fill:#333333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Qva2PI8ZFsmfbTwT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Qva2PI8ZFsmfbTwT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Qva2PI8ZFsmfbTwT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster text{fill:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT .cluster span{color:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Qva2PI8ZFsmfbTwT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Qva2PI8ZFsmfbTwT rect.text{fill:none;stroke-width:0;}#mermaid-svg-Qva2PI8ZFsmfbTwT .icon-shape,#mermaid-svg-Qva2PI8ZFsmfbTwT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Qva2PI8ZFsmfbTwT .icon-shape p,#mermaid-svg-Qva2PI8ZFsmfbTwT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Qva2PI8ZFsmfbTwT .icon-shape .label rect,#mermaid-svg-Qva2PI8ZFsmfbTwT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Qva2PI8ZFsmfbTwT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Qva2PI8ZFsmfbTwT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Qva2PI8ZFsmfbTwT :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Miniport Layer
NDIS Library
Protocol Layer
是
否
是
是
否
是
否
是
否
是
否
协议发送数据包
NdisSend / NdisSendPackets
ProSend / ProSendPackets
是回环包?
目标MAC == 本机MAC?
使用 DMA?
ProIndicatePacket 回环处理
GetScatterGatherList → DMA
proSendPacketToMiniport
ScatterGatherSendPacket 回调
proSendPacketToMiniport
WorkItemSend 正忙?
入队 MiniQueueWorkItem
MiniIsBusy?
入队工作项
直接调用微型端口
反序列化?
SendPacketsHandler/SendHandler
提升到 DISPATCH_LEVEL 再调用
硬件发送
发送完成中断
NdisMSendComplete
MiniSendComplete
释放 Scatter/Gather List
调用 ProtocolSendCompleteHandler
MiniWorkItemComplete 检查后续工作
5.3 数据包接收流程
#mermaid-svg-ro1A9uyE1FpkAo28{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ro1A9uyE1FpkAo28 .error-icon{fill:#552222;}#mermaid-svg-ro1A9uyE1FpkAo28 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ro1A9uyE1FpkAo28 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ro1A9uyE1FpkAo28 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ro1A9uyE1FpkAo28 .marker.cross{stroke:#333333;}#mermaid-svg-ro1A9uyE1FpkAo28 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ro1A9uyE1FpkAo28 p{margin:0;}#mermaid-svg-ro1A9uyE1FpkAo28 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster-label text{fill:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster-label span{color:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster-label span p{background-color:transparent;}#mermaid-svg-ro1A9uyE1FpkAo28 .label text,#mermaid-svg-ro1A9uyE1FpkAo28 span{fill:#333;color:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 .node rect,#mermaid-svg-ro1A9uyE1FpkAo28 .node circle,#mermaid-svg-ro1A9uyE1FpkAo28 .node ellipse,#mermaid-svg-ro1A9uyE1FpkAo28 .node polygon,#mermaid-svg-ro1A9uyE1FpkAo28 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ro1A9uyE1FpkAo28 .rough-node .label text,#mermaid-svg-ro1A9uyE1FpkAo28 .node .label text,#mermaid-svg-ro1A9uyE1FpkAo28 .image-shape .label,#mermaid-svg-ro1A9uyE1FpkAo28 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ro1A9uyE1FpkAo28 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ro1A9uyE1FpkAo28 .rough-node .label,#mermaid-svg-ro1A9uyE1FpkAo28 .node .label,#mermaid-svg-ro1A9uyE1FpkAo28 .image-shape .label,#mermaid-svg-ro1A9uyE1FpkAo28 .icon-shape .label{text-align:center;}#mermaid-svg-ro1A9uyE1FpkAo28 .node.clickable{cursor:pointer;}#mermaid-svg-ro1A9uyE1FpkAo28 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ro1A9uyE1FpkAo28 .arrowheadPath{fill:#333333;}#mermaid-svg-ro1A9uyE1FpkAo28 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ro1A9uyE1FpkAo28 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ro1A9uyE1FpkAo28 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ro1A9uyE1FpkAo28 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ro1A9uyE1FpkAo28 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ro1A9uyE1FpkAo28 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster text{fill:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 .cluster span{color:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ro1A9uyE1FpkAo28 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ro1A9uyE1FpkAo28 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ro1A9uyE1FpkAo28 .icon-shape,#mermaid-svg-ro1A9uyE1FpkAo28 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ro1A9uyE1FpkAo28 .icon-shape p,#mermaid-svg-ro1A9uyE1FpkAo28 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ro1A9uyE1FpkAo28 .icon-shape .label rect,#mermaid-svg-ro1A9uyE1FpkAo28 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ro1A9uyE1FpkAo28 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ro1A9uyE1FpkAo28 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ro1A9uyE1FpkAo28 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Packet Return
Receive Indication
DPC Stage
Hardware
传统 ReceiveHandler
Packet ReceivePacketHandler
是
否
是
是
否
否
是
否
网卡接收数据
硬件中断
MiniportISR
排队 DPC
HandleDeferredProcessing DPC
MiniportHandleInterrupt
MiniportEnableInterrupt
数据包指示方式?
EthFilterDprIndicateReceive
MiniIndicateReceivePacket
MiniIndicateData
遍历 ProtocolListHead
调用协议 ReceiveHandler
遍历协议设置 WrapperReserved 引用计数
协议有 ReceivePacketHandler?
协议 ReceivePacketHandler
增加包引用计数
复制数据到 LookaheadBuffer
调用协议 ReceiveHandler
反序列化?
引用计数 == 0?
立即调用 ReturnPacketHandler
协议后来调用 NdisReturnPackets
引用计数 == 0?
设置 NDIS_STATUS_SUCCESS
设置 NDIS_STATUS_PENDING
5.4 请求处理流程 (OID 查询/设置)
#mermaid-svg-dGPvbkzYbgquOAiX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dGPvbkzYbgquOAiX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dGPvbkzYbgquOAiX .error-icon{fill:#552222;}#mermaid-svg-dGPvbkzYbgquOAiX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dGPvbkzYbgquOAiX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dGPvbkzYbgquOAiX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dGPvbkzYbgquOAiX .marker.cross{stroke:#333333;}#mermaid-svg-dGPvbkzYbgquOAiX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dGPvbkzYbgquOAiX p{margin:0;}#mermaid-svg-dGPvbkzYbgquOAiX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dGPvbkzYbgquOAiX .cluster-label text{fill:#333;}#mermaid-svg-dGPvbkzYbgquOAiX .cluster-label span{color:#333;}#mermaid-svg-dGPvbkzYbgquOAiX .cluster-label span p{background-color:transparent;}#mermaid-svg-dGPvbkzYbgquOAiX .label text,#mermaid-svg-dGPvbkzYbgquOAiX span{fill:#333;color:#333;}#mermaid-svg-dGPvbkzYbgquOAiX .node rect,#mermaid-svg-dGPvbkzYbgquOAiX .node circle,#mermaid-svg-dGPvbkzYbgquOAiX .node ellipse,#mermaid-svg-dGPvbkzYbgquOAiX .node polygon,#mermaid-svg-dGPvbkzYbgquOAiX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dGPvbkzYbgquOAiX .rough-node .label text,#mermaid-svg-dGPvbkzYbgquOAiX .node .label text,#mermaid-svg-dGPvbkzYbgquOAiX .image-shape .label,#mermaid-svg-dGPvbkzYbgquOAiX .icon-shape .label{text-anchor:middle;}#mermaid-svg-dGPvbkzYbgquOAiX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dGPvbkzYbgquOAiX .rough-node .label,#mermaid-svg-dGPvbkzYbgquOAiX .node .label,#mermaid-svg-dGPvbkzYbgquOAiX .image-shape .label,#mermaid-svg-dGPvbkzYbgquOAiX .icon-shape .label{text-align:center;}#mermaid-svg-dGPvbkzYbgquOAiX .node.clickable{cursor:pointer;}#mermaid-svg-dGPvbkzYbgquOAiX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dGPvbkzYbgquOAiX .arrowheadPath{fill:#333333;}#mermaid-svg-dGPvbkzYbgquOAiX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dGPvbkzYbgquOAiX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dGPvbkzYbgquOAiX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dGPvbkzYbgquOAiX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dGPvbkzYbgquOAiX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dGPvbkzYbgquOAiX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dGPvbkzYbgquOAiX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dGPvbkzYbgquOAiX .cluster text{fill:#333;}#mermaid-svg-dGPvbkzYbgquOAiX .cluster span{color:#333;}#mermaid-svg-dGPvbkzYbgquOAiX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dGPvbkzYbgquOAiX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dGPvbkzYbgquOAiX rect.text{fill:none;stroke-width:0;}#mermaid-svg-dGPvbkzYbgquOAiX .icon-shape,#mermaid-svg-dGPvbkzYbgquOAiX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dGPvbkzYbgquOAiX .icon-shape p,#mermaid-svg-dGPvbkzYbgquOAiX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dGPvbkzYbgquOAiX .icon-shape .label rect,#mermaid-svg-dGPvbkzYbgquOAiX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dGPvbkzYbgquOAiX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dGPvbkzYbgquOAiX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dGPvbkzYbgquOAiX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
无
NdisRequestQueryInformation
NdisRequestSetInformation
有
是
否
协议调用 NdisRequest
ProRequest
MiniIsBusy?
入队工作项 NdisWorkItemRequest
MiniDoRequest
有 CoRequestHandler?
请求类型
MiniportQueryInformationHandler
MiniportSetInformationHandler
MiniportCoRequestHandler
状态 == PENDING?
等待 MiniRequestComplete
直接完成
MiniRequestComplete
调用 RequestCompleteHandler
MiniWorkItemComplete
5.5 适配器重置流程
#mermaid-svg-K4bXZDTKrdVgaPvU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-K4bXZDTKrdVgaPvU .error-icon{fill:#552222;}#mermaid-svg-K4bXZDTKrdVgaPvU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-K4bXZDTKrdVgaPvU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-K4bXZDTKrdVgaPvU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-K4bXZDTKrdVgaPvU .marker.cross{stroke:#333333;}#mermaid-svg-K4bXZDTKrdVgaPvU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-K4bXZDTKrdVgaPvU p{margin:0;}#mermaid-svg-K4bXZDTKrdVgaPvU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster-label text{fill:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster-label span{color:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster-label span p{background-color:transparent;}#mermaid-svg-K4bXZDTKrdVgaPvU .label text,#mermaid-svg-K4bXZDTKrdVgaPvU span{fill:#333;color:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU .node rect,#mermaid-svg-K4bXZDTKrdVgaPvU .node circle,#mermaid-svg-K4bXZDTKrdVgaPvU .node ellipse,#mermaid-svg-K4bXZDTKrdVgaPvU .node polygon,#mermaid-svg-K4bXZDTKrdVgaPvU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-K4bXZDTKrdVgaPvU .rough-node .label text,#mermaid-svg-K4bXZDTKrdVgaPvU .node .label text,#mermaid-svg-K4bXZDTKrdVgaPvU .image-shape .label,#mermaid-svg-K4bXZDTKrdVgaPvU .icon-shape .label{text-anchor:middle;}#mermaid-svg-K4bXZDTKrdVgaPvU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-K4bXZDTKrdVgaPvU .rough-node .label,#mermaid-svg-K4bXZDTKrdVgaPvU .node .label,#mermaid-svg-K4bXZDTKrdVgaPvU .image-shape .label,#mermaid-svg-K4bXZDTKrdVgaPvU .icon-shape .label{text-align:center;}#mermaid-svg-K4bXZDTKrdVgaPvU .node.clickable{cursor:pointer;}#mermaid-svg-K4bXZDTKrdVgaPvU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-K4bXZDTKrdVgaPvU .arrowheadPath{fill:#333333;}#mermaid-svg-K4bXZDTKrdVgaPvU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-K4bXZDTKrdVgaPvU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-K4bXZDTKrdVgaPvU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K4bXZDTKrdVgaPvU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-K4bXZDTKrdVgaPvU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K4bXZDTKrdVgaPvU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster text{fill:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU .cluster span{color:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-K4bXZDTKrdVgaPvU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-K4bXZDTKrdVgaPvU rect.text{fill:none;stroke-width:0;}#mermaid-svg-K4bXZDTKrdVgaPvU .icon-shape,#mermaid-svg-K4bXZDTKrdVgaPvU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K4bXZDTKrdVgaPvU .icon-shape p,#mermaid-svg-K4bXZDTKrdVgaPvU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-K4bXZDTKrdVgaPvU .icon-shape .label rect,#mermaid-svg-K4bXZDTKrdVgaPvU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K4bXZDTKrdVgaPvU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-K4bXZDTKrdVgaPvU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-K4bXZDTKrdVgaPvU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
否
协议调用 NdisReset
ProReset
MiniReset
MiniIsBusy?
入队重置工作项
NdisMIndicateStatus RESET_START
调用 MiniportResetHandler
状态 == PENDING?
等待 MiniResetComplete
执行寻址重置
NdisMIndicateStatus RESET_END
MiniWorkItemComplete
6. 数据流图
6.1 发送数据流
协议驱动 NDIS 库 微型端口驱动
+——–+ +———–+ +————+
| TCP/IP | | ndis.sys | | e1000.sys |
+——–+ +———–+ +————+
| | |
|— NdisSend(Packet) ———->| |
| | |
| +—–+—–+ |
| | ProSend() | |
| +—–+—–+ |
| | |
| +—–v—–+ |
| | 检查回环 |—如果目标=本机MAC–+ |
| +—–+—–+ | |
| | | |
| +—–v—–+ v |
| | DMA? |—是–> Scatter/Gather |
| +—–+—–+ | |
| | | |
| +—–v—–+ | |
| | 发送到 | | |
| | 微型端口 |<——————+ |
| +—–+—–+ |
| | |
| +—–v—–+ |
| | 序列化/ | |
| | 工作项队列 | |
| +—–+—–+ |
| | |
| +——- MiniportSend ———>|
| | (或 SendPackets) |
| | |
| | +—v—+
| | | 硬件 |
| | | 发送 |
| | +—v—+
| | |
| |<——- NdisMSendComplete —+
| | |
| +—–v—–+ |
| |MiniSendComplete |
| +—–+—–+ |
| | |
|<—— SendCompleteHandler —-+ |
6.2 接收数据流
硬件 NDIS 库 协议驱动
+——–+ +———–+ +——–+
| 网卡 | | ndis.sys | | TCP/IP |
+——–+ +———–+ +——–+
| | |
|— 硬件中断 ——————>| |
| | |
| +—–v—–+ |
| | MiniportISR| |
| +—–+—–+ |
| | |
| +—–v—–+ |
| | DPC 处理 | |
| +—–+—–+ |
| | |
|<– MiniportHandleInterrupt —-+ |
| | |
|— MiniportTransferData[可选] ->| |
| (或 NdisMIndicateReceivePacket)| |
| | |
| +—–v—–+ |
| | 以太网 | |
| | 过滤器检查 | |
| +—–+—–+ |
| | |
| +—–v——+ |
| | 遍历协议列表 | |
| +—–+——+ |
| | |
| +——- ReceiveHandler ——–>|
| | (或 ReceivePacketHandler)|
| | |
| | +—v—+
| | | 协议 |
| | | 处理 |
| | | 数据 |
| | +—v—+
| | |
|<— NdisReturnPackets ———+<— 协议归还数据包 ————+
6.3 OID 查询/设置数据流
协议驱动 NDIS 库 微型端口驱动
+——–+ +———–+ +————+
| TCP/IP | | ndis.sys | | e1000.sys |
+——–+ +———–+ +————+
| | |
|— NdisRequest(Request) ——>| |
| (OID_GEN_xxx…) | |
| +—–v—–+ |
| | ProRequest| |
| +—–+—–+ |
| | |
| +—–v——+ |
| | MiniDoRequest| |
| +—–+——+ |
| | |
| +—–v——+ |
| | 根据请求类型 | |
| +—–+——+ |
| | |
| +————+————-+ |
| | | |
| +——–v——+ +——–v——+ |
| |QueryInfoHandler| |SetInfoHandler | |
| +——–+——+ +——–+——+ |
| | | |
| +—— 微型端口执行 ——-+–> [硬件查询] |
| | (OID 处理) | |
| | | |
| +—— NdisM[Query/Set] –+ |
| | InformationComplete| |
| | | |
| +———-v———-+ |
| | MiniRequestComplete | |
| +———-+———-+ |
| | |
|<——— RequestCompleteHandler –+ |
7. 初始化序列
7.1 完整的系统启动-网络初始化序列
Phase 1: NDIS 自身初始化
=========================
1. 系统加载 ndis.sys
2. DriverEntry() 调用
– 初始化 ProtocolListHead, MiniportListHead, AdapterListHead
– 初始化对应的自旋锁
Phase 2: 微型端口驱动加载
=========================
3. 系统加载 e1000.sys 等微型端口驱动
4. DriverEntry 调用:
a. NdisMInitializeWrapper() – 在全局 MiniportListHead 注册驱动块
b. NdisMRegisterMiniport() – 注册微型端口特性
– 验证函数指针
– 注册 AddDevice = NdisIAddDevice
– 注册 MajorFunction = NdisGenericIrpHandler
Phase 3: PnP 枚举设备
=====================
5. PnP 管理器枚举 PCI 总线上的网络设备
6. NdisIAddDevice() 调用:
a. 读取注册表 Export 名称
b. IoCreateDevice() 创建设备对象
c. 初始化 LOGICAL_ADAPTER
d. 注册网络设备接口
e. IoAttachDeviceToDeviceStack() 附加到设备栈
f. 初始化挂起检测 DPC 和计时器
7. IRP_MN_START_DEVICE 到达:
a. NdisIPnPStartDevice() 调用
b. 打开注册表读取配置
c. 设置内部处理函数钩子
d. 调用 MiniportInitialize() – 微型端口初始化硬件
e. 查询 MAC 能力 (OID_GEN_MAC_OPTIONS, OID_802_3_CURRENT_ADDRESS 等)
f. 创建以太网过滤器
g. 启动挂起检测计时器 (默认每2秒检查)
h. 绑定所有已注册协议到本适配器
Phase 4: 协议驱动加载
=====================
8. 系统加载 tcpip.sys 等协议驱动
9. DriverEntry 调用:
a. NdisRegisterProtocol() – 注册协议特性
b. ndisBindMiniportsToProtocol() – 读取 Linkage\\Bind 键
c. 对每个适配器调用 BindAdapterHandler
d. BindAdapterHandler 调用 NdisOpenAdapter()
– MiniLocateDevice() 查找适配器
– 检查介质类型
– 分配 ADAPTER_BINDING
– 建立双向链表关系
Phase 5: 协议就绪
=================
10. NdisCompleteBindAdapter() 确认绑定完成
11. 协议驱动发送 NetEventBindsComplete PnP 事件
12. 网络协议栈开始正常收发数据
8. 关键函数分析
8.1 发送路径关键函数
| NdisSend | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L1272-L1285) | 协议入口,委托给 ProSend |
| ProSend | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L472-L574) | 检查回环 → DMA → 调用 proSendPacketToMiniport |
| proSendPacketToMiniport | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L388-L470) | 检查繁忙→序列化/非序列化→调用微型端口 |
| MiniSendComplete | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L529-L579) | 释放 Scatter/Gather 列表→回调协议SendCompleteHandler |
| MiniQueueWorkItem | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L980-L1046) | 尾部插入工作项 |
| MiniportWorker | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L1222-L1379) | 工作线程调度器,处理各种工作类型 |
8.2 接收路径关键函数
| MiniIndicateData | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L175-L251) | 遍历协议列表,调用每个协议的 ReceiveHandler |
| MiniIndicateReceivePacket | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L292-L432) | 处理 Packet 数组指示,管理引用计数 |
| NdisReturnPackets | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L256-L290) | 递减引用计数,减到0时调用 ReturnPacketHandler |
| EthFilterDprIndicateReceive | [efilter.c](file:///d:/reactos/drivers/network/ndis/ndis/efilter.c#L69-L99) | 以太网接收到入口,过滤后传递到 MiniIndicateData |
8.3 请求处理关键函数
| NdisRequest | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L1239-L1252) | 协议入口,委托给 ProRequest |
| ProRequest | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L307-L345) | 填充 MacBlock → 检查繁忙→MiniDoRequest |
| MiniDoRequest | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L1106-L1179) | 分发到 QueryInformation/SetInformation/CoRequest Handler |
| MiniQueryInformation | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L804-L862) | 同步/异步包装器,通过事件等待完成 |
| MiniRequestComplete | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L480-L527) | 请求完成处理,通知协议或信号事件 |
8.4 注册和绑定关键函数
| NdisMRegisterMiniport | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L2709-L2861) | 注册微型端口特性 |
| NdisRegisterProtocol | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L1112-L1232) | 注册协议特性并绑定适配器 |
| NdisOpenAdapter | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L762-L874) | 协议打开一个适配器建立绑定 |
| ndisBindMiniportsToProtocol | [protocol.c](file:///d:/reactos/drivers/network/ndis/ndis/protocol.c#L906-L1107) | 将协议绑定到所有适配器 |
| MiniLocateDevice | [miniport.c](file:///d:/reactos/drivers/network/ndis/ndis/miniport.c#L689-L753) | 按名称在全局列表查找适配器 |
8.5 缓冲区管理关键函数
| NdisAllocatePacketPoolEx | [buffer.c](file:///d:/reactos/drivers/network/ndis/ndis/buffer.c#L447-L521) | 分配数据包池,创建空闲链表 |
| NdisDprAllocatePacketNonInterlocked | [buffer.c](file:///d:/reactos/drivers/network/ndis/ndis/buffer.c#L683-L728) | 无锁分配,从空闲链表取一个 |
| NdisAllocateBuffer | [buffer.c](file:///d:/reactos/drivers/network/ndis/ndis/buffer.c#L336-L364) | 分配 MDL 作为 NDIS 缓冲区 |
| NdisGetFirstBufferFromPacket | [buffer.c](file:///d:/reactos/drivers/network/ndis/ndis/buffer.c#L871-L910) | 遍历数据包获取第一个缓冲区和总长度 |
| CopyBufferChainToBuffer | [buffer.c](file:///d:/reactos/drivers/network/ndis/ndis/buffer.c#L113-L169) | 从 MDL 链复制到连续缓冲区 |
8.6 中断处理关键函数
| ServiceRoutine | [io.c](file:///d:/reactos/drivers/network/ndis/ndis/io.c#L49-L79) | ISR,调用 MiniportISR 判断中断来源 |
| HandleDeferredProcessing | [io.c](file:///d:/reactos/drivers/network/ndis/ndis/io.c#L16-L47) | DPC,调用 MiniportHandleInterrupt+EnableInterrupt |
9. 构建配置
9.1 CMakeLists.txt
add_definitions(
-DNDIS_WRAPPER
-DNDIS51
-DNDIS51_MINIPORT
-DNDIS_MINIPORT_DRIVER
-DNDIS_LEGACY_DRIVER=1
-DNDIS_LEGACY_MINIPORT=1
-DNDIS_LEGACY_PROTOCOL=1)
add_library(ndis MODULE …)
set_module_type(ndis kernelmodedriver)
add_importlibs(ndis ntoskrnl hal)
9.2 输出
编译结果为 reactos/system32/drivers/ndis.sys,链接 ntoskrnl 和 hal。
9.3 版本声明
NDIS_VERSION = 0x00050001 (= NDIS 5.1)
附录 A:NDIS 协议驱动特性结构
typedef struct _NDIS_PROTOCOL_CHARACTERISTICS {
UCHAR MajorNdisVersion; // NDIS 主版本
UCHAR MinorNdisVersion; // NDIS 次版本
USHORT Reserved; // 保留
NDIS_STRING Name; // 协议名称
OPEN_ADAPTER_COMPLETE_HANDLER OpenAdapterCompleteHandler;
CLOSE_ADAPTER_COMPLETE_HANDLER CloseAdapterCompleteHandler;
SEND_COMPLETE_HANDLER SendCompleteHandler;
TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler;
RECEIVE_HANDLER ReceiveHandler;
RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler;
STATUS_HANDLER StatusHandler;
STATUS_COMPLETE_HANDLER StatusCompleteHandler;
BIND_ADAPTER_HANDLER BindAdapterHandler;
UNBIND_ADAPTER_HANDLER UnbindAdapterHandler;
PNP_EVENT_HANDLER PnPEventHandler; // NDIS 5.0
RECEIVE_PACKET_HANDLER ReceivePacketHandler; // NDIS 5.0
SEND_COMPLETE_HANDLER SendCompleteHandler;
...
} NDIS_PROTOCOL_CHARACTERISTICS;
附录 B:NDIS 微型端口驱动特性结构
typedef struct _NDIS_MINIPORT_CHARACTERISTICS {
UCHAR MajorNdisVersion;
UCHAR MinorNdisVersion;
USHORT Filler;
UINT Reserved;
CHECK_FOR_HANG_HANDLER CheckForHangHandler;
DISABLE_INTERRUPT_HANDLER DisableInterruptHandler;
ENABLE_INTERRUPT_HANDLER EnableInterruptHandler;
HALT_HANDLER HaltHandler;
HANDLE_INTERRUPT_HANDLER HandleInterruptHandler;
INITIALIZE_HANDLER InitializeHandler;
ISR_HANDLER ISRHandler;
QUERY_INFORMATION_HANDLER QueryInformationHandler;
RESET_HANDLER ResetHandler;
SEND_HANDLER SendHandler; // NDIS 3.0/4.0
SET_INFORMATION_HANDLER SetInformationHandler;
TRANSFER_DATA_HANDLER TransferDataHandler;
RETURN_PACKET_HANDLER ReturnPacketHandler; // NDIS 4.0
SEND_PACKETS_HANDLER SendPacketsHandler; // NDIS 4.0
...
} NDIS_MINIPORT_CHARACTERISTICS;
附录 C:参考文档
- NDIS 5.1 规范 (MSDN)
- [ddk/ndis.h](file:///d:/reactos/sdk/include/ddk/ndis.h) — NDIS DDK 头文件
- [ddk/ndisguid.h](file:///d:/reactos/sdk/include/ddk/ndisguid.h) — NDIS GUID 定义
- [psdk/ntddndis.h](file:///d:/reactos/sdk/include/psdk/ntddndis.h) — NDIS IOCTL 定义
网硕互联帮助中心




评论前必须登录!
注册