内核下面分配内存很简单. 我倒. 比3环下面还简单呢. 3环还需要调用两次函数, 0环更加方便.. 呵呵! 当然这只是使用上了. 内核中比用户态多了个后备列表内存(LookasideList),这翻译真是差劲..不过我看kmdkit里面也是这样翻译. 就将就着用吧! 还有的中文书籍好像根本就不翻译.. 估计也是不知道应该怎么翻译吧!

内核中还有个舒服的双向链表可以供使用. 估计是因为链表太常用了. 自己倒腾出来的链表每次写项目都改一次. 悲剧.. 还是系统直接提供好啊!这个双向链表也是非常容易使用的, 只是在遍历的时候我没搞明白. 咋个都不说遍历这个问题呢? 难道链表不需要遍历的么? 后来请教了杀哥才知道. 我倒还是需要自己写遍历函数. 不过挺简单, 这个就不算了!

这个后备列表内存, 也是比较好用. 使用也简单, 还有一些内存操作的函数, 这些函数在Win32下面也是有的, 所以直接划过..

```c++ /* Windows内核下链表和后备列表操作! 编译方法参见makefile. */ #include ; #define ARRAY_NUMBER 50 #define BUFFER_SIZE 1024 #include ;

typedef struct tagDATA { DWORD dwValue; LIST_ENTRY ListEntry; }DATA, *PDATA; //=========================================================================== // 内核中的链表使用. 非常舒服啊 #pragma code_seg( "INIT" ) VOID TestLinkList() { ULONG i; PDATA pData = NULL; PLIST_ENTRY pEntry; LIST_ENTRY ListHead; //初始化链表 InitializeListHead( &ListHead );

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//在链表从头部开始插入10个元素
KdPrint(( "\nBegin insert to link list Head!\n"; ));
for( i = 0; i <= 10; i++, pData = NULL ) {
    pData = (PDATA)ExAllocatePool( PagedPool, sizeof(DATA) );
    if ( !pData ) {
        KdPrint(( "Memory Alloccation Error!\n"; ));
        return;
    }

    pData->dwValue = i;

    //在头部进行插入
    InsertHeadList( &ListHead, &pData->ListEntry );
}

//————————————————————————— //从链表尾部中取出, 并显示 KdPrint(( “\nBegin remove from link list Tail!\n” ));

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
for( ;!IsListEmpty(&ListHead); pData = NULL ) {

    pEntry = RemoveTailList( &ListHead );

    //获取我们的数据指针
    pData = CONTAINING_RECORD( pEntry, DATA, ListEntry );
    if ( !pData ) {
        KdPrint(( "Get Data Error!\n" ));
        return;
    }

    KdPrint(( "%d\t", pData->dwValue ));
    ExFreePool( pData );
}

//=========================================================================== //在链表尾部插入10个元素 KdPrint(( “\nBegin insert to link list Tail!\n”; )); for( i = 0; i <= 10; i++, pData = NULL ) { pData = (PDATA)ExAllocatePool( PagedPool, sizeof(DATA) ); if ( !pData ) { KdPrint(( “Memory Alloccation Error!\n”; )); return; }

1
2
3
4
5
    pData->dwValue = i;

    //在尾部进行插入
    InsertTailList( &ListHead, &pData->ListEntry  );
}

//=========================================================================== //遍历链表, 从头往后面遍历 KdPrint(( “\nTraverse the list!\n” )); for( pEntry = ListHead.Flink; pEntry != &ListHead; pEntry = pEntry->Flink, pData = NULL ) {

1
2
3
4
    //获取数据指针
    pData = CONTAINING_RECORD( pEntry,DATA, ListEntry );
    KdPrint(( "%d\t", pData->dwValue ));
}

//=========================================================================== //从链表头部, 并显示 KdPrint(( “\nBegin remove from link list\n” ));

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
for( ;!IsListEmpty( &ListHead ); pData = NULL ) {

    //从链表头部进行删除
    PLIST_ENTRY pEntry = RemoveHeadList( &ListHead );

    //获取我们的数据指针
    pData = CONTAINING_RECORD(pEntry, DATA, ListEntry  );
    if ( !pData ) {
        KdPrint(( "Get Data Error!\n" ));
        return;
    }

    KdPrint(( "%d \t", pData->dwValue ));
    ExFreePool( pData );
}

} //=========================================================================== // 内核中的后备列表的使用.后备列表使用太简单了还没有kmdkit的例子号 #pragma code_seg( “INIT” ) VOID LookasideTest() { int i; PDATA MyDataArr[ARRAY_NUMBER] = {0}; PAGED_LOOKASIDE_LIST PageLookaside;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
KdPrint(( "Lookaside的使用!\n" ));

//初始化分页后备列表,还有一个非分页的..
ExInitializePagedLookasideList( &PageLookaside,NULL,NULL,0,sizeof(DATA), "1234", 0 );

//模拟频繁申请内存
for ( i=0; i &lt; ARRAY_NUMBER; i++ ) {
    MyDataArr[i] = (PDATA)ExAllocateFromPagedLookasideList( &amp;PageLookaside );

    RtlFillBytes( MyDataArr[i], sizeof(DATA), 0 );
    MyDataArr[i]-&gt;dwValue = i;
}

//模拟频繁回收内存
for ( i = 0 ; i &lt; ARRAY_NUMBER; i++ ) {

    KdPrint(( "%d\t", MyDataArr[i]-&gt;dwValue ));

    RtlZeroBytes( MyDataArr[i], sizeof(DATA) );
    ExFreeToPagedLookasideList( &amp;PageLookaside, MyDataArr[i] );
    MyDataArr[i] = NULL;
}

//删除Lookaside对象
ExDeletePagedLookasideList( &amp;PageLookaside );
KdPrint(( "\nLookaside 使用完成!\n" ));

} //=========================================================================== //内核中一些内存方面的函数使用, Win32下面也是有的, 差不多了 #pragma code_seg( “INIT” ) VOID RtlTest() { PUCHAR pBuffer = NULL; PUCHAR pBuffer2 = NULL; ULONG ulRet;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
//分配分页内存, 并用0填充
pBuffer = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
RtlZeroMemory(pBuffer,BUFFER_SIZE);

//分配分页内存, 并用0xAA填充
pBuffer2 = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
RtlFillMemory(pBuffer2,BUFFER_SIZE,0xAA);

//内存拷贝
RtlCopyMemory( pBuffer, pBuffer2,BUFFER_SIZE );

//判断内存是否一致
ulRet = RtlCompareMemory( pBuffer,pBuffer2, BUFFER_SIZE );
if ( ulRet == BUFFER_SIZE ) {
    KdPrint(( "两块内存完全相等.\n" ));
}else {
    KdPrint(( "两块内存并不完全相等.\n" ));
}

}

NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzReg ) {

1
2
3
4
TestLinkList();             //链表测试
LookasideTest();            //后备列表内存测试
RtlTest();              //常用内存函数测试
return -1;

}