Delphi研究之驅動開發篇(五)

2021-12-29 16:34:53 字數 3138 閱讀 8211

作 者: mickeylan

時 間: 2008-02-03,11:24

鏈 接: 

上篇教程我們介紹了驅動開發中如何使用系統記憶體堆,這一節讓我們看看後備列表的使用。堆管理器管理著系統和使用者堆,它把堆空間分為相同尺寸的塊(block)。堆管理器會根據堆分配請求,去選擇乙個合適尺寸的未使用的塊。顯然,這個過程需要點時間。如果你需要固定尺寸的記憶體塊,但是你事先並不知道它的大小和使用頻率,這樣的話為了效能的原因,你還是使用後備列表(lookaside lists)吧,後備列表是只有核心模式才有的。

後備列表和系統記憶體池的主要的區別是什麼呢?後備列表只可以分配固定大小的事先定義尺寸的記憶體塊。後備列表會快很多,因為它不需要去搜尋可用的未分配的記憶體。

當你剛接觸後備列表,你需要解決的問題不是怎麼建立後備列表,而是管理你要分配的記憶體塊。

具體來說,你把你要使用和釋放的記憶體存貯在**? 怎麼存貯?這不是個簡單的問題,因為你不知道塊的數量。有三種結構來解決這個問題:

◎ 單向鍊錶(singly linked list)

◎ s-list排序的單向鍊錶(s-list, sequenced singly-linked list) (單向鍊錶的改進)

◎ 雙向鍊錶(doubly linked list)

我們將只接觸雙向鍊錶,因為它最通用。

如果你是第一次接觸後備列表和雙向鍊錶這些概念,你會覺得下面的**有點複雜,但實際上它們是非常簡單的。

後備列表(lookaside list)和雙向鍊錶(doubly linked list)的英文名稱都有乙個"list",但是它們是完全不同的。後備列表是一組事先分配的相同尺寸的記憶體塊。這些塊有些在使用,有些沒被使用。當有記憶體分配請求的時候,系統會遍歷這個列表尋找最近的未分配的塊。如果未分配的塊找到了,分配請求就很快被滿足了。否則系統必須從分頁或不分頁記憶體池去分配。根據列表中分配行為發生的頻率,系統會自動調整未分配塊的數量來滿足分配請求,分配的頻率越高,會有越多的塊被儲存在後備列表中。後備列表如果總是不被使用,也會自動減少空間大小。

雙向鍊錶是資料組織的一種形式。可以很方便地把同類結構連線在一起,並且很容易遍歷。雙向鍊錶被系統廣泛地使用來處理內部結構。

我想了半天,也沒有找到乙個適合的簡單的例子。所以下面這個驅動程式好像意義不大。但是可以幫助你理解相關的概念,還有雙向鍊錶。

這裡也沒有提供驅動控制程式。你可以使用kmdkit4d 包中的kmdmanager 或者類似的工具,還可以使用debu**iew或softice 控制台來檢視除錯資訊。

**:unit lookasidelist;

inte***ce

uses

nt_status, ntoskrnl, macros;

function _driverentry(pdriverobject: pdriver_object;

pusregistrypath: punicode_string): ntstatus; stdcall;

implementation

type

psome_structure = ^some_structure;

some_structure = record

somefield1: dword;

somefield2: dword;

listentry: list_entry;              

somefieldx: dword;

end;

var    g_ppagedlookasidelist: ppaged_lookaside_list;

g_listhead: list_entry;

g_dwindex: dword;

dwcnt: dword;

procedure addentry;

var    pentry: psome_structure;

begin

pentry := exallocatefrompagedlookasidelist(g_ppagedlookasidelist);

if pentry <> nil then

begin

dbgprint(lookasidelist: + memory block allocated from lookaside list at address %08x#13#10, pentry);

memset(pentry, 0, sizeof(some_structure));

insertheadlist(@g_listhead, @pentry^.listentry);

inc(g_dwindex);

pentry^.somefield1 := g_dwindex;

dbgprint(lookasidelist: + entry #%d added#13#10, pentry^.somefield1);

end else

begin

dbgprint(lookasidelist: very bad. couldnt allocate from lookaside list#13#10);

end;

end;

procedure removeentry;

var    pentry, ptemp: pointer;

ss: some_structure;

offs: dword;

begin

if islistempty(@g_listhead) <> true then

begin

offs := dword(@ss.listentry) - dword(@ss);

pentry := removeheadlist(@g_listhead);

ptemp := pointer(dword(pentry) - offs);

dbgprint(lookasidelist: - entry #%d removed#13#10,

psome_structure(ptemp)^.somefield1);

exfreetopagedlookasidelist(g_ppagedlookasidelist, ptemp);

dbgprint(lookasidelist: - memory block at address %08x returned to lookaside list#13#10, ptemp);

end else

begin

&n

function object研究之五

boost提供了從 1到 9的佔位符。具體定義如下 boost arg 1 1 boost arg 2 2 boost arg 3 3 boost arg 4 4 boost arg 5 5 boost arg 6 6 boost arg 7 7 boost arg 8 8 boost arg 9 ...

WDM驅動程式開發之環境配置篇

乙個星期前郭老師給我布置了一項任務 開發我們自己設計的一塊板子的pci裝置驅動,並給我指出了方向,具體說就是 三步走 戰略 1 入門。熟悉基於driverstudio開發環境的裝置驅動開發,同時側面了解pci裝置驅動程式的相關知識。2 高階。運用純ddk進行驅動開發,著重於學習別人的例項,並能熟練進...

OFBIZ研究心得之五

6.3 ofbiz資料庫實體引擎配置 6.3.1 建立資料庫表 apache ofbiz的實體引擎支援從簡單的xml檔案中定義資料庫表結構,然後自動在資料庫中建表,並生成對映物件,這樣的好處是大大簡化了資料庫的構建流程 6 下面以本系統中的乙個例項說明如何實現。一般需要用到兩個檔案 entitymo...