驅動開發(4)核心中的記憶體分配和錯誤碼
在驅動開發中,我們不應該使用C/C++執行時函式中的malloc或者calloc函式分配記憶體,更不應該使用new關鍵字,因為核心中的記憶體分配需要特殊處理。
在應用程式中,每個應用都有2G的虛擬記憶體,因此記憶體並不緊張,而所有的驅動程式共用核心模式的2G虛擬記憶體,因此核心中的資源非常寶貴,應該儘量節省。
更可怕的是記憶體洩露,應用程式即使發生了記憶體洩露,在其結束時作業系統可以通過程序上下文中的虛擬記憶體頁面對映關係,釋放這一部分虛擬記憶體對應的實體記憶體,但是驅動程式如果申請虛擬記憶體後不釋放,結果就是在系統重新啟動之前這一部分地址所在的記憶體頁面一直處於“被申請未釋放”的狀態,想想那種情景吧。如果驅動程式申請的虛擬記憶體位於非頁記憶體池,那麼是不能交換到磁碟檔案中的,因此這一部分虛擬記憶體對應的實體記憶體也一直無法空閒出來,後果更加嚴重。
核心中申請虛擬記憶體的函式一般有這麼幾個:ExAllocatePool(WithTag)、ExAllocatePoolWithQuota(Tag)、ExFreePool(WithTag),我們來看看這兩個ExAllocatePool(申請核心虛擬記憶體)和ExFreePool(釋放核心虛擬記憶體),其他的都差不多,具體可以看MSDN。
PVOID ExAllocatePool(
_In_ POOL_TYPE PoolType,
_In_ SIZE_T NumberOfBytes
);
PoolType:指定的池記憶體分配的型別。請參閱 POOL_TYPE。
常用的有:
NonPagedPool:從非分頁記憶體池中分配虛擬記憶體
PagedPool:從分頁記憶體池中分配虛擬記憶體
NumberOfBytes:指定要分配的位元組數。
返回值:成功返回分配的記憶體指標,失敗返回NULL。
VOID ExFreePool(
_In_ PVOID P
);
P:指定要釋放的記憶體塊的地址。
還有一點時間,說說核心中的錯誤碼NTSTATUS吧
32位系統下,NTSTATUS是unsigned long型別,核心中的函式的返回值以及我們以後處理派遣函式等等都會用到。
其中,STATUS_SUCCESS表示成功 ,可以用NT_SUCCESS巨集判斷是否是STATUS_SUCCESS 。
自然還有很多其他的錯誤碼,比如
STATUS_UNSUCCESS(不成功)
STATUS_ACCESS_DENIED(訪問被拒絕)
STATUS_IN_PAGE_ERROR(頁故障)
等等