关于解决应用层提取NDIS驱动数据包丢包的方案,通过event加共享内存实现

DDS实现层深度解析:实时系统中的RTPS协议、内存与QoS硬核调优 DDS(Data Distribution Service)作为分布式实时系统的通信中间件,其核心价值在于将发布-订阅抽象模型落地为纳秒级确定性的二进制实现。它依托RTPS有线协议,在操作系统、CPU缓存、网络硬件与实时调度约束下完成协议栈映射、零拷贝传输、静态内存池分配及QoS语义到OS原语的精准翻译。技术关键点包括共享内存(SHM)替代UDP内核路径以降低延迟、缓存行对齐规避伪共享、RTPS报文精简优化处理耗时,以及基于CLOCK_TAI的时间戳统一机制。本文聚焦DDS implementations在 阅读详情
关于解决应用层提取NDIS驱动数据包丢包的方案,通过event加共享内存实现
截获的网络封包,很多时候都需要将包的信息或者是包的内容通过win32层显示出来,很多人想到的方法是event加IOCTL,不过这样很容易产生丢包的问题,因为网络接受发送数据包的速度原比event 和 IOCTL的速度要快,也就是说当一个event发到win32层时,win32层通过DeviceIoControl得到数据的时候,原来自己预先定义的缓冲区已经被覆盖了多少遍了。在网上听过高手们通过信号加队列来实现,来一个包信号自加1,win32层来读队列,读一个包信号自减1,不过我翻MSDN好几遍,也没有找到信号量到底是什么东西,只有自己琢磨。
我实现的方法和信号量加队列有点相类似,是通过event和共享内存实现。我实现的比较简单,没有将包的内容提取,只是将包的类型地址信息传到win32层进行显示。
想必如何进行driver和win32通讯和通过共享内存进行传输数据已经很熟悉了吧,(如果不懂可以去www.driverdevelop.com论坛去看看吧,上面还有例子,我就不在这里充了)。我申请了1K字节的内存空间,然后定义包的信息结构
typedef struct _WY_RECORD //日志
{
unsigned char WY_SourceIP[4];
unsigned char WY_DestinationIP[4];
unsigned short WY_SourcePort;
unsigned short WY_DestinationPort;
unsigned char WY_Protocol;
unsigned char WY_Action; //对数据包的执行动作
union{
unsigned short WY_TCPCode; //TCP数据包类型
struct{ //ICMP数据包类型和代码
unsigned char WY_Type;
unsigned char WY_Code;
};
};
unsigned long WY_distance; //下一个数据包的偏移量
}WY_RECORD,*WY_PRECORD;
#define RECORD_LENGTH 20
我在内存区域开始的四个字节区域划定了一个结构--日志头。通过它来标示剩下1020个字节中包的分布情况
typedef struct _WY_RECORD_HEADER
{
unsigned char WY_FirstRec; //第一个日志的位置
unsigned char WY_LastRec; //最后一个日志的位置
unsigned short WY_RecNum; //日志数量
}WY_RECORDHEAD,*WY_PRECORDHEAD;
这个内存区域能放51个日志,不过这已经很足够了,因为通常一个通知event到达win32层,win32层准备开始接受数据的时候有三个数据包在内存区域中。WY_LastRec由driver来修改,每增加一个包则自加1,当到达最大时判断WY_RecNum是否为最大,否则从第零块区域填入数据,是则说明win32层没有接受日志则往后都不填充。win32层修改WY_FirstRec,每读取一个数据包则自加1,当WY_RecNum == 0时,停止读。
event如何发送,如果当前上个WY_RecNum == 0 时则发送event,因此需要有一个变量来记录上一次WY_RecNum的值,用全局变量WY_LastNum来保存上一个数值
以下是Driver中添加日志的函数,编码风格是我自创的(WY命名规则)
int WYFilter_AddRecord(IN WY_PRECORD WY_pRecord, IN int WY_isSend)
{
KSPIN_LOCK WY_Spinlock;
KIRQL WY_OldIrql;
if(WY_pRecHeader->WY_RecNum < 51){
if(WY_pRecHeader->WY_FirstRec==0 && WY_pRecHeader->WY_LastRec==0){ file://如果缓冲区尚未记录
WY_pRecord->WY_distance = (WY_pRecHeader->WY_LastRec+1)*RECORD_LENGTH; file://计算下一个日志块的偏移量
memcpy(WY_pRecAddr,(PVOID)WY_pRecord,RECORD_LENGTH);
WY_pRecHeader->WY_LastRec++;
WY_pRecHeader->WY_RecNum++;
KeSetEvent(WY_gbEvt,0,FALSE);
WY_LastRecNum++;
}
else{ //已经记录过

if(WY_pRecHeader->WY_LastRec == 50){
WY_pRecord->WY_distance = 0; //计算下一个日志块的偏移量
memcpy(((WY_PRECORD)WY_pRecAddr+WY_pRecHeader->WY_LastRec),(PVOID)WY_pRecord,RECORD_LENGTH);
WY_pRecHeader->WY_LastRec = 0; //计算最后一个日志块所在的块数
WY_LastRecNum = WY_pRecHeader->WY_RecNum;
}
else{

WY_pRecord->WY_distance = (WY_pRecHeader->WY_LastRec+1)*RECORD_LENGTH;//计算下一个日志块的偏移量
//第一个参数是计算当前需要写入的日志块的实际地址
memcpy(((WY_PRECORD)WY_pRecAddr+WY_pRecHeader->WY_LastRec),(PVOID)WY_pRecord,RECORD_LENGTH);
WY_pRecHeader->WY_LastRec++; //计算最后一个日志块所在的块数
WY_LastRecNum = WY_pRecHeader->WY_RecNum;
}
KeAcquireSpinLock(&WY_Spinlock,&WY_OldIrql);
WY_pRecHeader->WY_RecNum++; //计算日志块数
KeReleaseSpinLock(&WY_Spinlock,WY_OldIrql);
if(WY_LastRecNum == 0 && WY_pRecHeader->WY_RecNum != 0){
KeSetEvent(WY_gbEvt,0,FALSE);
}

}
// return WYFilter_CheckPolicy(&WY_pRecord->WY_PacketContent,WY_isSend); //这里的结构与我的有些出入,
//将最后一个DWORD数据去掉,就是这个结构
}
// return WYFilter_CheckPolicy(&WY_pRecord->WY_PacketContent,WY_isSend);
}
以下时win32层进行读取
DWORD WINAPI GetRecord(LPVOID WY_lpParam)
{
WY_PRECORDHEAD WY_pRecHeader;
WY_PRECORD WY_pRecord;
WY_PRECORD WY_pRecAddr;
CTestDlg *WY_pThis = (CTestDlg*)WY_lpParam;
CCriticalSection WY_cs;
// DWORD WY_dwReturn;

WY_pRecHeader = (WY_PRECORDHEAD)WY_pThis->WY_RecordAddr; //初始化内存地址
WY_pRecord = (WY_PRECORD)(((unsigned long)WY_pThis->WY_RecordAddr)+4);
WY_pRecAddr = (WY_PRECORD)(((unsigned long)WY_pThis->WY_RecordAddr)+4);
// WY_pThis->WY_result.Format("%x",WY_pRecord);
// WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
// WY_pThis->WY_result.Format("%x",WY_pRecAddr);
// WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
while(TRUE){
::WaitForSingleObject(WY_pThis->WY_hEvt,INFINITE);
while(WY_pRecHeader->WY_RecNum > 0){
if(WY_pRecHeader->WY_FirstRec < 50){

// WY_pThis->WY_result.Format("Record Number = %d,First Record : %d,Last Record : %d",WY_pRecHeader->WY_RecNum,WY_pRecHeader->WY_FirstRec,WY_pRecHeader->WY_LastRec);
// WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
WY_pThis->WY_result.Format("%d.%d.%d.%d:%d-->%d.%d.%d.%d:%d %x",
WY_pRecord->WY_PacketContent.WY_SourceIP[0],
WY_pRecord->WY_PacketContent.WY_SourceIP[1],
WY_pRecord->WY_PacketContent.WY_SourceIP[2],
WY_pRecord->WY_PacketContent.WY_SourceIP[3],
WY_pRecord->WY_PacketContent.WY_SourcePort,
WY_pRecord->WY_PacketContent.WY_DestinationIP[0],
WY_pRecord->WY_PacketContent.WY_DestinationIP[1],
WY_pRecord->WY_PacketContent.WY_DestinationIP[2],
WY_pRecord->WY_PacketContent.WY_DestinationIP[3],
WY_pRecord->WY_PacketContent.WY_DestinationPort,
WY_pRecord->WY_PacketContent.WY_Protocol
);
WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
WY_pRecord = (WY_PRECORD)(((unsigned long)WY_pRecAddr)+WY_pRecord->WY_distance);
WY_pRecHeader->WY_FirstRec++;
}
else{

// WY_pThis->WY_result.Format("Record Number = %d,First Record : %d,Last Record : %d",WY_pRecHeader->WY_RecNum,WY_pRecHeader->WY_FirstRec,WY_pRecHeader->WY_LastRec);
// WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
WY_pThis->WY_result.Format("%d.%d.%d.%d:%d-->%d.%d.%d.%d:%d %x",
WY_pRecord->WY_PacketContent.WY_SourceIP[0],
WY_pRecord->WY_PacketContent.WY_SourceIP[1],
WY_pRecord->WY_PacketContent.WY_SourceIP[2],
WY_pRecord->WY_PacketContent.WY_SourceIP[3],
WY_pRecord->WY_PacketContent.WY_SourcePort,
WY_pRecord->WY_PacketContent.WY_DestinationIP[0],
WY_pRecord->WY_PacketContent.WY_DestinationIP[1],
WY_pRecord->WY_PacketContent.WY_DestinationIP[2],
WY_pRecord->WY_PacketContent.WY_DestinationIP[3],
WY_pRecord->WY_PacketContent.WY_DestinationPort,
WY_pRecord->WY_PacketContent.WY_Protocol
);
WY_pThis->WY_List1.AddString(WY_pThis->WY_result);
WY_pRecord = (WY_PRECORD)(((unsigned long)WY_pRecAddr)+WY_pRecord->WY_distance);
WY_pRecHeader->WY_FirstRec = 0;

}
WY_cs.Lock();
WY_pRecHeader->WY_RecNum--;
WY_cs.Unlock();
}

}

} 
安卓通用rndis驱动 安卓手机在电脑上共享网络提示安装rndis驱动使用。 立即下载

相关推荐

AWS RDS 介绍 三)创建 RDS 实例

AWS RDS 介绍 共分为 7 个部分, 其中 第 3部分重点介绍,如何创建一个RDS 实例。 三) AWS RDS 试用MySQL http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.MySQL.

XuYongshi02的专栏 7648

DKMS解决nvidia-smi驱动丢失的问题

DKMS(Dynamic Kernel Module Support)是DELL的一个项目,可以做到内核变更后自动编译模块,适配新内核。有时在重启机器后,nvidia-smi之后会显示nvidia驱动丢失,这是由于linux内核升级,之前的nvidia驱动就不匹配连接。命令运行之后,nvidia-smi之后正常显示。可以看到有一个nvidia的文件,比如。

winycg的博客 7170

手把手教你为STM32设备生成自定义MAC地址(基于芯片ID的5种算法对比)

本文详细介绍了基于STM32芯片ID生成自定义MAC地址的5种算法,包括直接截取、异或折叠、CRC32哈希、自定义混合运算及SHA-256摘要。通过对比分析各算法的计算复杂度、唯一性及适用场景,帮助嵌入式开发者根据项目规模与资源,选择最合适的方案,确保设备MAC地址的唯一性与合规性。

weixin_29170327的博客 528

NDIS驱动开发-NET_BUFFER体系

NDIS NET_BUFFER系列

王马的博客 1706

给大一新生的蓝桥杯EDA备赛规划:从电路分析到立创EDA,如何用一年时间高效备赛?

本文为大一新生提供了一份系统的蓝桥杯EDA备赛规划,从电路分析基础到立创EDA实战操作,分阶段指导如何高效备赛。内容涵盖理论学习、软件操作、PCB设计专项提升及冲刺优化策略,帮助学生在一年内全面提升电子设计能力,为竞赛做好充分准备。

weixin_31476015的博客 291

python实现ECMS算法

ECMS(Equivalent Consumption Minimization Strategy)算法是一种用于混合动力汽车能量管理系统的优化策略。它通过计算等效油耗来平衡电池电量消耗和燃油消耗,从而优化整体能耗。以下是一个简单的Python实现,用于演示ECMS算法的基本思想。这个实现假设了一个简单的混合动力汽车模型,其中电池电量和燃油消耗是主要的优化目标。

weixin_45570158的博客 924

NDIS IM调试遇到的问题:OID_TCP_TASK_OFFLOAD

这几天调试NDIS xLan的时候,发现在 win2003上运行不正常,以前在 XP,WIN7,WIN8上测试都能正常,于是查找原因。 先说说这驱动是干什么的,这是个NDIS中间驱动,采用应用层拦截的方式处理数据包, 就是在中间驱动里获得的数据包,发送到应用层程序,应用层程序分析处理之后再返回给中间驱动。 很类似应用层防火墙的功能,数据包的拦截处理全在应用层完成。 类似的实现,可参看 li

fanxiushu的专栏 2285

【星火】海思HI3516C开发板实战:基于LVGL与MPP库的行车记录仪/电子显微镜方案

本文详细介绍了基于海思HI3516CV500开发板,结合LVGL图形库与海思MPP媒体处理平台,实现行车记录仪与电子显微镜方案的完整实战过程。内容涵盖从系统环境搭建、驱动配置到应用开发的全流程,重点解析了MPP视频流处理管道与LVGUI界面协同工作的核心机制,为嵌入式音视频开发提供了可复用的参考方案。

weixin_42126677的博客 163

在驱动程序和应用程序间共享内存

文章更新:在驱动和应用程序间共享内存译自:The NT Insider November-December 2007 Volume 14 Issue 4译者:lioqio[编辑提示:《The NT Insider》将陆续对以前文章进行维护修正,以便确认这些文章针对Windows的大多数当前版本是正确的,并且反映了最好的工程实践。这篇文章是OSR在线上最频繁被引用的文章之一,作为

2471

DaVinci Developer中枚举类型变量的创建与实战应用

本文详细介绍了在DaVinci Developer中创建和使用枚举类型变量的方法与实战应用。通过智能温控系统的案例,阐述了枚举类型在嵌入式开发中的核心价值,包括提升代码可读性、类型安全性和维护便捷性。文章还提供了枚举类型在状态机实现和多模块协同中的高级应用技巧,以及调试与优化的实用建议。

ik678901234的博客 512

YOLOv8改进策略【YOLO和Mamba】| 2024 VM-UNet,高效的特征提取模块VSS block 二次创新提高精度

VM-UNet模型设计的出发点是解决现有CNN-based和模型在医学图像分割中的局限性,利用(SSMs)的优势,提出一种更有效的医学图像分割模型。具体来说,CNN-based模型在捕捉长距离信息方面存在不足,而模型由于自注意力机制的二次复杂度导致计算负担较重。SSMs模型如Mamba不仅在建模长距离依赖方面表现出色,还具有线性计算复杂度,这为VM-UNet的设计提供了理论基础。

Limiiiing的博客 626

Wireshark按进程过滤:基于ETW与Npcap实现网络流量精准分析

网络协议分析是理解网络通信、排查故障的基础技术,其核心在于对数据包的捕获、解析与过滤。传统过滤方式依赖IP、端口等网络层信息,但在复杂场景下,如多进程共享端口或进程动态使用多个连接时,难以精准定位流量来源。其实现原理在于打通网络数据包与操作系统进程间的信息壁垒,通过在数据包捕获点(如系统调用接口)同步记录进程标识符(PID),并将此元数据嵌入抓包文件。这项技术的核心价值在于实现了从“网络五元组”到“具体进程”的视角跃升,为软件调试、性能瓶颈定位、恶意软件行为分析和隐私监控提供了关键上下文。应用场景广泛覆盖开

weixin_33843409的博客 391

NL2SQL实践系列(1):深入解析Prompt工程在text2sql中的应用技巧

NL2SQL实践系列(1):深入解析Prompt工程在text2sql中的应用技巧

丨汀、的博客 4328

内存映射 驱动与应用层程序共享内存

下面说说内存映射。由于我们的程序需要传输大量的数据,如前所述,能尽量减少内存拷贝对于系统的性能都会有很大的提高。所以当有数据包要在用户态程序和驱动程序之间交互的时候,尽可能地避免直接拷贝大量数据。而应该使用内存映射的方法使用户态程序和驱动程序共用一段内存,这样就可以避免不少的内存拷贝。要进行内存映射,首先要申请一块不分页(NonPaged)的内存,这里由驱动程序来完成。然后为...

weixin_33936401的博客 358

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Linux主机USB RNDIS网卡驱动实现不完整导致的一例问题

某通信模块设备,通过USB提供RDNIS和ECM网卡功能。在实际应用中发现,USB RNDIS网卡模式下,当使用AT指令以不同的CID拨号的时候,在Windows主机上能正常拨号成功,但在Linux主机上却会发生拨号失败的情况。作为对比,在同样的测试环境和测试方法下,USB ECM网卡则没有这种异常。 测试流程概括如下: - 设备侧已经配置为USB RNDIS模式 - 主机侧通过AT指令以CID1拨号成功 -测试网络功能,主机和设备侧可以ping通 - 主机侧通过AT指令断开CID1拨号 -主机侧...

nidongla的博客 3312

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Linux丢包问题排查思路

Linux 丢包排查

djp304的博客 6498

常用串口调试工具比较(详细)

目前有许多免费的串口调试工具,比较常用的有:1、友善串口调试助手(v2.6.5)优点: 1)使用方便,不丢包; 2)串口自动识别,支持COM9以上串口; 3)支持多串口调试; 4)支持历史发送记录; 5)广泛支持各种波特率,高达10 Mbps以上波特率,具体和电脑硬件有关。 下载地址:http://rj.baidu.com/soft/detail/27520.html?ald缺点:会丢失数据,刷屏...

无语僧 16万+

【大杂烩】杂7杂8的东西

记录平时工作的内容和体会

vickytong1018的博客 2万+

USB基本知识(二)

<br />usb作为一种串行接口,应用日益广泛。如同每个工程设计人员必须掌握I2C,RS232这些接口一样,我们也必须掌握usb.<br />但是usb的接口协议实在有点费解,linux uhci驱动作者之一Alan Stern曾经就说过“The USB documentation is downright evil. Most    of it is just crap, written by a committee. You're better off ignoring most of it ”。<b

小破猴的专栏 860

解决服务器UDP数据包丢失问题

Severe UDP packet loss While looking after a UDP based service, it came to my attention that we were losing a significant number of inbound packets. The first place to start is with netstat(8) and

xianweijian的博客 1万+

在Linux 上,编写一个每秒接收 100万UDP数据包的程序究竟有多难?

在Linux 上,编写一个每秒接收 100万UDP数据包的程序究竟有多难? 写的不错,转载一下 1. UDP概念    用户数据报协议(英语:User Datagram Protocol,缩写为 UDP),又称使用者资料包协定,是一个简单的面向数据报的传输层协议,正式规范为RFC 768    在TCP/IP模型中,UDP为网络层以上和应用层以下提供了一个简单的接口。U

xingzheouc的专栏 1万+

NDIS 函 数 简 明 手 册

函数 描述无连接微端口的上层函数 DriverEntry 由操作系统调用来激活和初始化微端口驱动程序MiniportAllocateComple 调用它来指示以前调用的NdisMAllocateMemoryAsync已经完成MiniportCheckForHang 检查NIC的内部状态MiniportDisableInterrupt 禁止NIC产生中断MiniportEnableInterrupt

Léon Atelier 1719

C++ 入门笔记(十七):list 入门 —— 为什么 list 不能 sort?

第17课:用大白话讲清 list 的双向链表结构、哨兵头、push_back 四步、迭代器封装、merge 与 splice 的区别,以及 vector 排序为什么常比 list 快。

wo_jack的博客 259
上一篇: NDIS resources
下一篇: MS Windows Animated Cursor (.ANI) Local Overflow Exploit
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值