NDIS 库 (ndis.sys) 驱动程序分析

NDIS 库 (ndis.sys) 驱动程序分析

目录

  1. 概述
  2. 框架结构
  3. 核心数据结构
  4. 核心模块分析
  5. 工作流程图
  6. 数据流图
  7. 初始化序列
  8. 关键函数分析
  9. 构建配置

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 框架下运行时,两者呈现出截然不同的设计哲学。

对比维度Windows NDIS 设计Linux 网络驱动设计
核心架构三层严格分层:协议驱动 → NDIS 库 → 微型端口驱动。NDIS 作为独立的内核模块存在,承担调度和管理职责两层轻量架构:协议栈直接调用 net_device_ops 中的函数指针,没有独立的"中间库层",驱动模型由内核统一框架提供
数据包表示NDIS_PACKET + NDIS_BUFFER (MDL):基于 Windows MDL (Memory Descriptor List) 机制,包描述符和数据分离,通过 MDL 链支持 Scatter/Gather I/Ostruct sk_buff:统一的缓冲区结构,使用 head/data/tail/end 四个指针灵活管理协议头空间,支持克隆 (skb_clone)、共享、分片 (skb_shinfo),内联了全套操作函数
发送模型异步回调驱动MiniportSend[Packets] 返回 NDIS_STATUS_PENDING 表示异步,发送完成后调用 NdisMSendComplete() 回调协议。NDIS 库负责任何必要的序列化和排队同步+流量控制dev->hard_start_xmit(skb) 同步发送,返回 NETDEV_TX_OKNETDEV_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 + MiniportEnableInterrupthardIRQ + softIRQ 两阶段:硬中断(仅做最小处理,如获取数据)→ softIRQNET_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_OPTIONSOID_802_3_CURRENT_ADDRESS)区分操作类型。NDIS 提供 NdisReadConfigurationNdisOpenConfiguration 等注册表封装分散的接口:通过多个 net_device_ops 函数实现(ndo_do_ioctlndo_get_statsndo_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_ADAPTERDMA_OPERATIONS通用 DMA APIdma_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.c40stubs.c50stubs.c 提供桩函数内核版本绑定:驱动必须针对特定内核版本编译,net_device_ops 结构在不同内核版本间有较大差异,不保证二进制兼容性
工作项延迟处理NDIS 工作项队列MiniQueueWorkItem + MiniportWorker 实现串行化的工作项调度,支持 NdisWorkItemSendNdisWorkItemRequestNdisWorkItemResetRequested 等工作类型,通过内核 IoQueueWorkItem 实现workqueue/tasklet:Linux 内核提供通用的 work_struct + schedule_work()tasklet 机制,驱动根据自己的需要使用这些通用机制,没有 NDIS 这样专门针对网络驱动的专用工作项队列

1.4 NDIS 这样设计的优缺点

优点:

  1. 驱动开发简化:微型端口驱动只需关注硬件操作本身,填写标准回调函数表即可。发送/接收的序列化、协议绑定管理、PnP 协调等复杂工作由 NDIS 代劳
  2. 二进制兼容性好:同一份微型端口驱动编译后在支持 NDIS 5.x 的 Windows 版本上均可运行,降低维护成本
  3. 统一的配置管理:通过 OID 机制和 NdisReadConfiguration 封装,驱动不需要直接与注册表打交道
  4. 版本平滑演进:通过不断扩展 MiniportCharacteristics 结构大小而不是修改函数签名,保持了向后的二进制兼容性
  5. 热插拔支持完善:PnP 事件经过 NDIS 统一调度后转发给协议驱动,确保所有绑定协议都能正确响应设备插拔

缺点:

  1. 性能开销:相比 Linux 的轻量模型,额外的 NDIS 层带来了函数调用开销和上下文切换(尤其在工作项队列场景)
  2. 灵活性受限:驱动必须在 NDIS 的框架内工作,无法绕过 NDIS 层直接操作协议栈
  3. 缺少 NAPI 等效的轮询机制:NDIS 5.1 仅支持中断驱动的推模式,高负载下可能产生大量中断(Linux NAPI 在 Linux 2.6 中引入以解决此问题)
  4. 依赖注册表:绑定配置和参数配置强依赖注册表,嵌入式场景下不够灵活

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.cPCI 配置空间读写、资源分配
control.c读写锁同步
efilter.c以太网帧过滤
object.cNDIS 6.0 通用对象接口
workitem.cNDIS 6.0 工作项接口
time.c计时器管理
string.c字符串操作
misc.c杂项(互锁操作、字符串比较)
cl.c面向连接客户端
cm.c呼叫管理器
co.c面向连接支持
30stubs.cNDIS 3.0 兼容性桩函数
40stubs.cNDIS 4.0 兼容性桩函数
50stubs.cNDIS 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 函数执行以下初始化:

  1. 初始化全局协议列表 ProtocolListHead 和对应的自旋锁
  2. 初始化全局微型端口列表 MiniportListHead 和对应的自旋锁
  3. 初始化全局适配器列表 AdapterListHead 和对应的自旋锁
  4. 注册卸载处理函数 MainUnload
  5. 初始化取消 ID 计数器

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)

  1. 从注册表读取 Export 名称
  2. 调用 IoCreateDevice 创建 FILE_DEVICE_PHYSICAL_NETCARD 设备
  3. 初始化 LOGICAL_ADAPTER 结构
  4. 注册网络设备接口 (GUID_DEVINTERFACE_NET)
  5. 附加到设备栈
  6. 初始化计时器和 DPC(用于检测挂起)

设备启动 (NdisIPnPStartDevice)

  1. 将适配器加入全局列表
  2. 打开注册表键,读取总线类型/编号/槽号
  3. 设置回调处理函数
  4. 调用 MiniportInitialize
  5. 查询 MAC 选项、硬件地址、lookahead 大小、最大发送包数
  6. 创建以太网过滤器 (EthCreateFilter)
  7. 启动挂起检测计时器
  8. 绑定所有协议到新适配器

设备停止 (NdisIPnPStopDevice)

  1. 从全局列表移除适配器
  2. 取消计时器
  3. 调用 MiniportHalt
  4. 释放资源(内存、过滤器)
4.2.3 工作项队列

NDIS 使用工作项队列来序列化对微型端口的操作:

MiniQueueWorkItem()   → 入队(尾插法)
MiniDequeueWorkItem() → 出队(头删法)  
MiniportWorker()      → 工作线程处理
MiniWorkItemComplete() → 完成并检查是否有后续工作项

工作类型包括发送、请求、重置等,通过 MiniportWorker 统一调度。

4.3 协议管理 (protocol.c)

4.3.1 协议注册 (NdisRegisterProtocol)
  1. 验证协议版本/特性
  2. 分配 PROTOCOL_BINDING 结构
  3. 复制特性(含大写化协议名)
  4. 调用 ndisBindMiniportsToProtocol 绑定适配器
  5. 发送 NetEventBindsComplete PnP 事件
  6. 加入全局协议列表
4.3.2 协议-适配器绑定 (ndisBindMiniportsToProtocol)

绑定过程:

  1. 构造注册表路径 \Registry\Machine\...\Services\{Protocol}\Linkage
  2. 读取 Bind 值(REG_MULTI_SZ 格式)
  3. 遍历每个设备名,检查是否已启动和是否已绑定
  4. 构造每适配器的参数路径
  5. 调用协议驱动的 BindAdapterHandler
4.3.3 适配器打开 (NdisOpenAdapter)
  1. 通过名称查找适配器 (MiniLocateDevice)
  2. 检查介质类型匹配
  3. 分配 ADAPTER_BINDING 结构
  4. 设置处理函数(Request, Reset, Send, SendPackets, TransferData)
  5. 将绑定加入协议和适配器的链表

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_CONTEXTMINIPORT_RESOURCE 链表实现。

4.7 以太网过滤 (efilter.c)

当微型端口指示接收到数据时,EthFilterDprIndicateReceive 被调用,它会:

  1. 检查以太网过滤器
  2. 调用 MiniIndicateData 将数据传递给绑定的协议

5. 工作流程图

5.1 驱动初始化流程

协议驱动注册

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 数据包发送流程

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 数据包接收流程

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 查询/设置)

NdisRequestQueryInformation

NdisRequestSetInformation

协议调用 NdisRequest

ProRequest

MiniIsBusy?

入队工作项 NdisWorkItemRequest

MiniDoRequest

有 CoRequestHandler?

请求类型

MiniportQueryInformationHandler

MiniportSetInformationHandler

MiniportCoRequestHandler

状态 == PENDING?

等待 MiniRequestComplete

直接完成

MiniRequestComplete

调用 RequestCompleteHandler

MiniWorkItemComplete

5.5 适配器重置流程

协议调用 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,链接 ntoskrnlhal

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 定义
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值