64位內核開發第十三講,內核中經常使用的鏈表等數據結構

內核中經常使用的數據結構

數據結構

1.何爲數據結構

無論是Ring0仍是Ring3數據結構都是必需要知道的.數據結構是一種思想.
以及怎麼存儲數據. 跟語言無關.平臺無關.數據結構

如:(鏈表,數組,棧,隊列.圖.樹...)ide

ring0下數據結構非彼數據結構. 意思就是數據結構思想都是同樣的.
你只須要熟悉ring0下數據結構怎麼定義的.以及使用便可.指針

ring0常見的數據結構:code

雙向鏈表隊列

** LIST_ENTRY**內存

** HASH 表
TREE 樹**it

** LookAside**class

2.方便使用的數據結構雙向鏈表 (LIST_ENTRY)

typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

FLINK(front)前向指針 指向後一個節點 BLink(back)後向指針.指向前邊的指針.List

相應的仍是 LIST_ENTRY64 以及 LIST_ENTRY32

typedef struct LIST_ENTRY32 {
    ULONG Flink;
    ULONG Blink;
} LIST_ENTRY32;
typedef LIST_ENTRY32 *PLIST_ENTRY32;
typedef struct LIST_ENTRY64 {
    ULONGLONG Flink;
    ULONGLONG Blink;
} LIST_ENTRY64;
typedef LIST_ENTRY64 *PLIST_ENTRY64;

求出結構體所在的位置

CONTAINING_RECORD(address,type,field);

展開:

#define CONTAINING_RECORD(address, type, field) ((type *)( \
                                                  (PCHAR)(address) - \
                                                  (ULONG_PTR)(&((type *)0)->field)))

使用方法:

它的做用就是求出field在type中的偏移.而後用address - 偏移 獲得位置.

以下:

typedef struct _MY_DATA
{
  ULONG a;
  ULONG b;
  LIST_ENTRY MyEntry;
}MY_DATA,*PMY_DATA

PMY_DATA plist;

PMY_DATA list = CONTAINING_RECORD(pList,MY_DATA,MyEntry);

尋找結構體的偏移.

3.list_entry 的使用

使用就很簡單了.跟鞋ring3代碼同樣.

LIST_ENTRY listHead; 
PMY_DATA plist; //對咱們自定義結構進行初始化.

InitializeListHead(&listHead); //初始化ListHead

//插入數據

InsertHeadLisst(&listHead,&plist->MyEntry);//將這個結構放到頭結點中.

InSertTailList(&listHead,&pList->MyEntry); //尾部插入.

PLIST_ENTRY pRemList = RemoveHeadList(&listHead); //移除頭結點
pRemList  pRemList = RemoveTailList(&listHead) //尾部移除.

二丶 平衡樹.

使用現成的樹. 在 wrk-v1.2\base\ntos\rtl裏面有一個文件

AvlTable.c. 這裏面就有樹.摳出代碼來便可使用.

WDK中 有一個樹 RTL_AVL_TABLE 這個是WDK中的.

能夠本身實現.也能夠本身作. 主要是要了解 LIST_ENTRY

三丶 LookAside結構.

咱們調用 malloc new 或者 ExAllocatePoolWithTag等分配內存的
時候.都會產生碎片.

而對於咱們頻繁分配內存.每次都是固定大小的時候.如結構體.
就可使用這個結構用來分配.

它有兩種分配類別. 一種是分頁內存.一種是非分頁內存.

** PAGED_LOOKASIDE_LIST ** 分頁
** NPAGED_LOOKASIDE_LIST ** 非分頁

使用方法:

PAGED_LOOKASIDE_LIST MyPagedList;

//第一步要初始化.你指定你要分配的大小
ExInitializePagedLookasideList(&MyPagedList,NULL,NULL,NULL,0,sizeof(MY_DATA),'BINI',0):
注意sizeof(MY_DATA) 這個是你指定的.

//分配內存
MY_DATA *pData = ExAllocatFromPagedLookasideList(&MyPagedList);

//釋放內存
ExFreeToPageLookasideList(&MyPagedList,pdata);//注意要還回去.

//卸載的時候要刪除
ExDeletPageLookasideList(&MyPagedList);
相關文章
相關標籤/搜索