您的位置:首页 > Web前端

个人总结NDIS中NDIS_PACKET,NDIS_BUFFER的关系

2012-08-02 13:14 281 查看
//
// NDIS_PACKET结构的定义
//
typedef struct _NDIS_PACKET
{
NDIS_PACKET_PRIVATE Private;
//这个其实是一个链表结构,Private.Head指向第一个链表,Private.Tail指向最后一个
//以下有关于这个结构的解释

union
{
struct // For Connection-less miniports
{
UCHAR MiniportReserved[2*sizeof(PVOID)];
UCHAR WrapperReserved[2*sizeof(PVOID)];
};

struct
{
//
// For de-serialized miniports. And by implication conn-oriented miniports.
// This is for the send-path only. Packets indicated will use WrapperReserved
// instead of WrapperReservedEx
//
UCHAR MiniportReservedEx[3*sizeof(PVOID)];
UCHAR WrapperReservedEx[sizeof(PVOID)];
};

struct
{
UCHAR MacReserved[4*sizeof(PVOID)];
};
};

ULONG_PTR Reserved[2]; // For compatibility with Win
UCHAR ProtocolReserved[1];

} NDIS_PACKET, *PNDIS_PACKET, **PPNDIS_PACKET;

// NDIS_PACKET_PRIVATE 的定义
typedef struct _NDIS_PACKET_PRIVATE
{
UINT PhysicalCount; // number of physical pages in packet.
UINT TotalLength; // Total amount of data in the packet.
PNDIS_BUFFER Head; // 链表指针,指向第一个
PNDIS_BUFFER Tail; // 链表指针,指向最后一个

// if Head is NULL the chain is empty; Tail doesn\'t have to be NULL also

PNDIS_PACKET_POOL Pool; // so we know where to free it back to
UINT Count;
ULONG Flags;
BOOLEAN ValidCounts;
UCHAR NdisPacketFlags; // See fPACKET_xxx bits below
USHORT NdisPacketOobOffset;
} NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE;

//NDIS_BUFFER定义 其实就是一个内存描述符

typedef struct _NDIS_BUFFER {
struct _NDIS_BUFFER *Next; //指向下一个节点的指针
PVOID VirtualAddress;      //指向报文首地址
PNDIS_BUFFER_POOL Pool;
UINT Length;               //报文数据长度
UINT Signature;
} NDIS_BUFFER, * PNDIS_BUFFER;


注释写的很清楚了 那么他们的关系还是不清楚的话看看附图



好了 这样一来我们的思路大概清楚了 NDIS_PACKET只不过是一个关于NDIS_BUFFER链表的结构 在NDIS_PACKET中的成员Private中有指向第一个NDIS_BUFFER的指针和指向最后一个NDIS_BUFFER的指针 分别是Private.Head和Private.Tail 而NDIS_BUFFER中就记录了我们数据包的地址和下一个NDIS_BUFFER的地址 操作有很多种方法 由于这些结构体本来对我们是不透明的
所以最安全的方法是用MS提供的一系列函数来操作NDIS_PACKET和NDIS_BUFFER

还是拿个例子好说话吧

NDIS_STATUS status ;
PNDIS_BUFFER NdisBuffer ;
UINT TotalPacketLength =, copysize =, DataOffset =, PhysicalBufferCount  ,  BufferCount   ;
PUCHAR mybuffer = NULL ,tembuffer = NULL ;

//假设这个是在PtReceive等函数中得到的PACKET
NdisQueryPacket(packet                     //我们先得到第一个NDISBUFFER 的指针
, &PhysicalBufferCount
, &BufferCount
,&NdisBuffer                               //NdisBuffer就是指向链表头
, &TotalPacketLength
);
/*
其实也可以不用那么麻烦 直接  NdisBuffer = packet->Private.Head ;就可以取得第一个BUFFER了
*/

status = NdisAllocateMemory( &mybuffer, 2048, 0, HighestAcceptableMax );  //分配我们自己的内存块

if( status != NDIS_STATUS_SUCCESS )
return NDIS_STATUS_FAILURE ;

NdisZeroMemory( mybuffer,) ;

NdisQueryBufferSafe(  //取得NDIS_BUFFER描述符中数据的首地址和大小
NdisBuffer,
&tembuffer,
©size,
NormalPagePriority
);

//将数据复制到我们的内存中
NdisMoveMemory(mybuffer, tembuffer, copysize) ;

DataOffset = copysize ;

while(1)
{
/*
也可以这样操作而不用NdisGetNextBuffer
if(NdisBuffer->Next == packet->Private.Tail )
break ;

NdisBuffer = NdisBuffer->Next ;

if(pmdl == NULL )
break ;
*/
//获得下一个NDIS_BUFFER的的指针
NdisGetNextBuffer(NdisBuffer , &NdisBuffer ) ;
如果指针是NULL  那么表示到链表尾了
if( NdisBuffer == NULL )
break ;

NdisQueryBufferSafe(
NdisBuffer,
&tembuffer,
©size,
NormalPagePriority
) ;

NdisMoveMemory( mybuffer + DataOffset , tembuffer, copysize) ;

DataOffset += copysize  ;

}

//OK  我们要的数据就全部都在我们申请的内存mybuffer 数据大小为DataOffset


转自:http://www.cppblog.com/ay19880703/archive/2008/09/18/62233.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: