【转】NDIS协议驱动笔记

简介: http://kruglinski.bokee.com/5746261.html   关键词: NDIS    Protocol    Driver    DDK    DriverStudio                                           今天终...

http://kruglinski.bokee.com/5746261.html

 

关键词NDIS    Protocol    Driver    DDK    DriverStudio                                          

今天终于把NDIS Protocol Driver开发相关的东东看完了,现在回头看其实协议驱动也不是很难,只是有些概念没有人点拨自己琢磨了很久,比如如何将收到的包写入上层应用程序ReadFile读取的buffer里,我的脑海里总有memcpy进行数据copy的概念,呵呵!

然而在NDIS协议驱动里copy数据不是通过memcpy这样的函数来完成的,这里有一个NDIS_PACKET的概念,当接收数据时先为NDIS_PACKET关联一个内存描述符NDIS_BUFFER(其实就是MDL),使用NdisChainBufferAtFront关联Buffer和Packet再调用NdisTransferData接收剩下的数据,ReceiveHandler和ReceivePacketHandler的处理方法是不一样的,ReceiveHandler先接收一个以太头然后按照我上面说的方法接收剩下的数据,因为要将头和余下数据都写入同一个块内存可能除了IRP里的MDL,还需要创建一个对同一个内存块不同位置的子描述符MDL.

而在ReceivePacketHandler里没有将以太头和数据包分开处理而是直接放在一个NDIS_PACKET里,所以只需要连接一个NDIS_BUFFER,然后使用NdisCopyFromPacketToPacket直接将数据copy进去即可.

在Windows 2000 DDK例子驱动Packet的PacketReceiveIndicate里可以看到先使用NdisMoveMappedMemory将以太头写入输出MDL指向的内存里,然后创建相同内存块的另一个子MDL跳过以太头,随后调用NdisChainBufferAtFront连接buffer到packet,最后调用NdisTransferData接收数据,并在TransferDataCompleteHandler将创建的子MDL删除,再将PacketRead时分配的NDIS_PACKET释放,并完成挂起的读请求IRP.

发送的概念很容易理解,主要就是调用NdisSend将数据从某个绑定的适配器(Adapter)发送出去,同样因为是异步的所以要处理SendCompleteHandler,主要就是将PacketWrite时分配的NDIS_PACKET包释放并完成挂起的写请求IRP.

而嗅探最常用的混杂模式是通过调用NdisRequest的发送NdisRequestSetInformation类型的OID_GEN_CURRENT_PACKET_FILTER请求,并使用NDIS_PACKET_TYPE_PROMISCUOUS参数.

主要就是要把大的流程把握清楚,其它细节的东西可以说的太多了.我觉得主要是由协议驱动设计所决定,而跟NDIS协议驱动本身的架构不是很相关,这里不再多说.

我觉得Windows 2000 DDK带的协议驱动例子是一个非常糟糕的例子,几乎没有可以分开解读的地方,必须一起读好几个函数,在某个函里会跟到一个NdisWaitEvent,然后又跳到另一个函数里看相关实现是怎么将事件设置成信号态的,某一个函数里引用一个全局变量的值,然后又要搜索在哪个函数里设置了这个全局变量值,怎么设置的,为什么那样设置,中间有太多的藕合,如控制设备和适配器逻辑设备使用同一组派遣函数(当然一个驱动对象也只能有一组,但在DriverStudio里经过包装后的驱动框架每个设备对象的派遣函数是不一样的,它们存在于不同的C++对象中),说到这里我一定要说一下DriverStudio里带的DriverNetworks有一个完全按照DDK Packet例子实现的驱动程序叫做nmPacket,在DriverNetworks的协议驱动框架里,分成四个C++对象,驱动对象,控制设备对象,适配器逻辑设备对象和协议绑定对象.

驱动对象里创建全局控制设备对象并注册协议绑定对象.协议绑定对象是对协议驱动的抽象,它的重载成员函数就是协议导出函数,在协议绑定对象的打开适配器虑函数Open里,创建一个适配器逻辑设备对象并传this指针.

协议绑定对象有一个静态链表成员,每次在适配器打开后(OpenComplete被调用时)加入一个条目,表示已经绑定的适配器,全局控制设备对象可以通过读这个成员取得绑定列表并返回给应用程序.适配器逻辑设备对象因为有协议绑定对象指针,可以随时调用协议驱动对象的相关功能(NdisSend,NdisRequest...),如在设备的Read派遣函数里在协议驱动对象的读链表里添加一个条目,随后协议绑定对象的接收函数里会从这个链表里取读取求,然后在在分割以太头和一次接收整个NDIS_PACKET的两个协议导出函数中接收数据,为读请求写入数据,并完成一个读操作.

DriverNetworks实现的这个协议驱动程序的面向对象抽象,功能划分与模块间解藕合做的非常非常好,代码可读性也非常好,编译好的驱动程序只比DDK的Packet只大一点点.我不是很清楚这么优秀的东东怎么没有流行起来,也或许已经非常流行只是我周围没有人用罢了,反正我是决定要把它用好,呵呵!

哈!在家的感觉真好......

 

【作者: kruglinski】【访问统计: 1534】【2006年10月11日 星期三 20:00】【 加入博采】【打印

目录
相关文章
|
缓存 安全 网络协议
Windows 安全基础——NetBIOS篇
Windows 安全基础——NetBIOS篇
389 4
|
11月前
|
数据采集 自然语言处理 NoSQL
Qwen for Tugraph:自然语言至图查询语言翻译大模型微调最佳实践
在图数据库的应用场景中,自然语言至图查询语言的高效转换一直是行业中的重要挑战。本次实践基于阿里云 Qwen 大模型,围绕 TuGraph 图数据库的需求,探索并验证了一套高效的大模型微调方案,显著提升了模型生成 Cypher 查询语句的能力。通过数据清洗、两阶段微调方法以及两模型推理框架等一系列创新策略,我们成功解决了图查询语言翻译任务中的核心问题。本文将从背景与目标、数据准备与清洗、微调框架设计、Prompt设计与优化、模型推理、最佳实践效果以及前景展望等六个部分出发,向读者逐步介绍我们的方案。
|
开发框架 .NET C#
C#学习相关系列之Linq用法---where和select用法(二)
C#学习相关系列之Linq用法---where和select用法(二)
1012 2
|
自然语言处理 JavaScript 前端开发
JDK序列化原理问题之FuryJDK序列化性能问题的如何解决
JDK序列化原理问题之FuryJDK序列化性能问题的如何解决
232 2
|
机器学习/深度学习 自然语言处理 语音技术
自然语言处理(NLP)中的语言模型
自然语言处理(NLP)中的语言模型
733 1
|
计算机视觉 C++ Python
OpenCV入门(C++/Python)- 使用OpenCV进行图像旋转和转换(五)
OpenCV入门(C++/Python)- 使用OpenCV进行图像旋转和转换(五)
635 0
|
存储 前端开发 Java
软件工程专业电商网站毕业论文答辩实录(基于SSM+VUE前后端分离的 “依伴汉服”网)
🍅程序员小王的博客:程序员小王的博客 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线
610 0
软件工程专业电商网站毕业论文答辩实录(基于SSM+VUE前后端分离的 “依伴汉服”网)
|
网络协议 C语言
邮件系统(基于SMTP协议和POP3协议-C语言实现)
邮件系统(基于SMTP协议和POP3协议-C语言实现)
邮件系统(基于SMTP协议和POP3协议-C语言实现)
|
自然语言处理 架构师 算法
15年架构师+6年CTO的P10大佬,道出架构真相!
15年架构师+6年CTO的P10大佬,道出架构真相!
490 0
|
缓存 Java Spring
Java:Spring Boot设置静态资源缓存方案-协商缓存
Java:Spring Boot设置静态资源缓存方案-协商缓存
555 0