鏈表的使用:
① 定義一個鏈表頭,單鏈表為SINGLE_LIST_ENTRY,雙鏈表為LIST_ENTRY。然後要對鏈表頭進行初始化。單鏈錶鏈表頭初始化要將它的Next域設為NULL,雙鏈表直接調用InitializeListHead。
② 往鏈表中插入元素:
對於單鏈表使用PushEntryList雙鏈表可以從鏈表頭也可以從鏈表尾插入:InsertHeadList,InsertTailList。這三個函數都有兩個參數,第一個參數為指向鏈表頭的指標,第二個參數為要插入的元素的連結域。
③ 從鏈表中刪除元素:
與插入元素類似,單鏈表使用PtryList,雙鏈表使用RemoveEntryList,RemoveHeadList,RemoveTailList。他們的參數都是指向鏈表頭的指標。
④ 為了得到鏈表中的元素,我們使用CONTAINING_RECORD宏。
後備鏈表
如果你需要固定尺寸的記憶體塊,但是你事先並不知道它的大小和使用頻率,這樣的話為了效能的原因,你還是使用後備列表(Lookaside Lists)吧,後備列表是只有核心模式才有的。
後備列表是一組事先分配的相同尺寸的記憶體塊。這些塊有些在使用,有些沒被使用。當有記憶體配置請求的時候,系統會遍曆這個列表尋找最近的未分配的塊。如果未分配的塊找到了,分配請求就很快被滿足了。否則系統必須從分頁或不分頁記憶體池去分配。根據列表中分配行為發生的頻率,系統會自動調整未分配塊的數量來滿足分配請求,分配的頻率越高,會有越多的塊被儲存在後備列表中。後備列表如果總是不被使用,也會自動減少空間大小。
使用後備鏈表:
① 為一個PAGED_LOOKASIDE_LIST或NPAGED_LOOKASIDE_LIST對象保留非分頁式記憶體。
這裡這兩種對象都是用來管理後備鏈表,它本身只能位於非分頁式記憶體,因為系統需要在提升的IRQL級上訪問它。這兩個對象十分相似,但分頁類型的鏈表使用FAST_MUTEX來同步,而非分頁類型的鏈表要使用自旋鎖。
② 調用相應的初始化函數對Lookaside鏈表進行初始化。
③ 從Lookaside鏈表上面分配儲存,使用AllocateFrom()函數。
④ 使用完之後,將從Lookaside上面申請的儲存空間返回Lookaside。
⑤ 調用Delete函數刪除鏈表。
|
服務函數 |
描述 |
|
ExInitializeNPagedLookasideList
ExInitializePagedLookasideList |
初始化lookaside鏈表 |
|
ExAllocateFromNPagedLookasideList
ExAllocateFromPagedLookasideList |
分配一個固定大小的記憶體塊 |
|
ExFreeToNPagedLookasideList
ExFreeToPagedLookasideList |
將一個記憶體塊釋放回lookaside鏈表 |
|
ExDeleteNPagedLookasideList
ExDeletePagedLookasideList |
刪除lookaside鏈表 |