1. 程式人生 > >【舊文章搬運】Windows控制代碼表分配演算法分析(三)

【舊文章搬運】Windows控制代碼表分配演算法分析(三)

原文發表於百度空間,2009-03-30
==========================================================================

三、當需要申請一個新的二級表(MidLevelTable)時,呼叫ExpAllocateMidLevelTable函式

PHANDLE_TABLE_ENTRY *
ExpAllocateMidLevelTable (
     IN PHANDLE_TABLE HandleTable,
     IN BOOLEAN DoInit,
     OUT PHANDLE_TABLE_ENTRY *pNewLowLevel
     )
/*++ Routine Description: This worker routine allocates a mid-level table. This is an array with pointers to low-level tables. It will allocate also a low-level table and will save it in the first index Note: The caller must have already locked the handle table Arguments: HandleTable - Supplies the handle table being used DoInit - If FALSE the caller (duplicate) does not want the free list build pNewLowLevel - Returns the new low level table for later free list chaining Return Value: Returns a pointer to the new mid-level table allocated --
*/ { PHANDLE_TABLE_ENTRY *NewMidLevel; PHANDLE_TABLE_ENTRY NewLowLevel; NewMidLevel = ExpAllocateTablePagedPool( HandleTable->QuotaProcess, PAGE_SIZE ); //申請一塊記憶體作為MidLevel,即二級表,大小為PAGE_SIZE,用以存放一級表的指標
if (NewMidLevel == NULL) { return NULL; } // // If we need a new mid-level, we'll need a low-level too. // We'll create one and if success we'll save it at the first position // NewLowLevel = ExpAllocateLowLevelTable( HandleTable, DoInit ); //申請一個一級表. //有人問過為什麼這個函式在申請二級表時同時還會申請一個一級表,看這個函式的呼叫時機就知道了. //呼叫過程ExCreateHandle->ExpAllocateHandleTableEntry->ExpAllocateHandleTableEntrySlow->ExpAllocateMidLevelTable //對ExCreateHandle更具體的分析,那是控制代碼分配的知識,稍後再說,以免偏題,現在只須知道呼叫ExpAllocateHandleTableEntrySlow時則表明控制代碼已達上限,需要再申請新的控制代碼表就行了 //而ExpAllocateHandleTableEntrySlow呼叫ExpAllocateMidLevelTable的第一個時機是TableLevel=0且控制代碼已達上限的時候, //這時候需要申請這個二級表,那就說明一級表不夠用了(三級表和二級表都只放指標,一級表中才是真正放內容的),需要再申請一個一級表,而兩個一級表就使得控制代碼表的級數躍升為兩級(MidLevel).
//所以,申請MidLevel的Table時其實就是稍帶著把再申請一個一級表的工作也做好了(同樣的,前面已經看到,申請HANDLE_TABLE時也是同時申請好了第一個一級表),這只是一級表躍升為二級表時的一個必做工作,僅此而已.
//總的說,二級表也只是框架,它有了內容(一級表)才能真正去放東西
//呼叫ExpAllocateMidLevelTable的另一種情況是此時TableLevel=2,但最後一個二級表已放滿了.此時要申請一個一級表就需要先申請一個新的二級表,情況和前面類似了 if (NewLowLevel == NULL) { ExpFreeTablePagedPool( HandleTable->QuotaProcess, NewMidLevel, PAGE_SIZE ); return NULL; } // // Set the low-level table at the first index // NewMidLevel[0] = NewLowLevel;//把這個新的一級表放入NewMidLevel[0],這個值後來則被放入了NewMidLevel[1],後面會分析到.而NewMidLevel[0]則存放最初的一級表(即升級為二級表之前的那個一級表),詳細程式碼見ExpAllocateHandleTableEntrySlow() *pNewLowLevel = NewLowLevel; return NewMidLevel; //新的二級表地址作為返回值 }

 

==============================================================================
五、控制代碼表的釋放比較簡單,遍歷並釋放每個一級表所佔記憶體就可以了~