【旧文章搬运】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; //新的二级表地址作为返回值 }

 

==============================================================================
五、句柄表的释放比较简单,遍历并释放每个一级表所占内存就可以了~

posted @ 2018-12-26 19:51  黑月教主  阅读(146)  评论(0编辑  收藏  举报