前言 :
在內核中還有另一個同步物件, 這就是互斥體物件. 前面已經介紹互斥體在應用程式中的使用, 在內核中使用互斥體物件的方法是相似的.
核心模式下的互斥體 :
互斥體在內核中的資料結構是 KMUTEX, 使用前需要初始化互斥體物件, 可以使用
KeInitializeMutex 內核函式, 其宣告如下 :
- Syntax :
- VOID KeInitializeMutex(
- __out PRKMUTEX Mutex,
- __in ULONG Level
- );
參數說明 :
* 參數 Mutex : 這個參數可以獲得內核互斥體物件的指標.
* 參數 Level : 保留值, 一般設為0.
初始化後的互斥體物件, 就可以使執行緒之間互斥了. 獲得互斥體物件用 KeWaitXX 系列內核函式, 釋放互斥體用
KeReleaseMutex 內核函式.
下面例子展示如何在驅動程式中使用互斥體物件, 首先這個例子新建兩個執行緒, 為了保證執行緒之間不並行執行, 執行緒間使用互斥體進行同步 :
- Driver.cpp : 示範在核心模式下使用 Mutex
- VOID MyMutexFun2(IN PVOID pContext)
- {
- PKMUTEX pkMutex = (PKMUTEX) pContext;
-
- KeWaitForSingleObject(pkMutex, Executive, KernelMode, FALSE, NULL);
- KdPrint(("Enter MyMutexFun2\n"));
-
- KdPrint(("\tExecution...\n"));
- KeStallExecutionProcessor(2000);
- KdPrint(("Leave MyMutexFun2\n"));
-
- KeReleaseMutex(pkMutex, FALSE);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
-
- VOID MyMutexFun1(IN PVOID pContext)
- {
- PKMUTEX pkMutex = (PKMUTEX) pContext;
-
- KeWaitForSingleObject(pkMutex, Executive, KernelMode, FALSE, NULL);
- KdPrint(("Enter MyMutexFun1\n"));
-
- KdPrint(("\tExecution...\n"));
- KeStallExecutionProcessor(2000);
- KdPrint(("Leave MyMutexFun1\n"));
-
- KeReleaseMutex(pkMutex, FALSE);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
-
- #pragma INITCODE
- VOID TestMutex()
- {
- HANDLE hMyThread1, hMyThread2;
- KMUTEX kMutex;
-
- KeInitializeMutex(&kMutex, 0);
-
- PsCreateSystemThread(&hMyThread1, 0, NULL, NtCurrentProcess(), NULL, MyMutexFun1, &kMutex);
- PsCreateSystemThread(&hMyThread2, 0, NULL, NtCurrentProcess(), NULL, MyMutexFun2, &kMutex);
- PVOID Pointer_Array[2];
- ObReferenceObjectByHandle(hMyThread1, 0, NULL, KernelMode, &Pointer_Array[0], NULL);
- ObReferenceObjectByHandle(hMyThread2, 0, NULL, KernelMode, &Pointer_Array[1], NULL);
-
-
- KeWaitForMultipleObjects(2, Pointer_Array, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
- ObDereferenceObject(Pointer_Array[0]);
- ObDereferenceObject(Pointer_Array[1]);
- KdPrint(("After KeWaitForMultipleObjects\n"));
- }
底下是執行結果, 查看驅動程式輸出 log 資訊, 可以看出兩個執行緒是以序列方式執行, 這意味著成功地進行同步 :
快速互斥體 :
快速互斥體 (Fast Mutex) 是 DDK 提供的另一種內核同步物件. 它的特性類似前面介紹的普通互斥體物件. 快速互斥體和普通互斥體起到作用完全一樣, 之所以被稱為快速互斥體, 是因為執行速度比普通互斥體快 (這裡指的是獲取與釋放的速度). 然而
快速互斥體比普通互斥體多了一個缺點, 就是不能遞迴的獲取互斥體物件. 遞迴的獲取指的是已經獲得互斥體的執行緒, 可以再次獲得這個互斥體. 換句話說互斥體只是互斥其他執行緒, 而不互斥自己所在的的執行緒, 但是快速互斥體則不允許遞迴的情況.
普通互斥體在內核中是用 MUTEX 資料結構描述的, 而快速互斥體在內核中是用 FAST_MUTEX 資料結構描述的. 除此之外對快速互斥體的初始化, 獲取和釋放對應的內核函式也和普通互斥體不同. 初始化快速互斥體的內核函式是
ExInitializeFastMutex, 獲取快速互斥體的內核函式是
ExAcquireFastMutex, 釋放快速互斥體的函式是
ExReleaseFastMutex. 下面例子展示了如何在驅動程式中使用快速互斥體 :
- Driver.cpp : 示範在核心模式下使用 FAST_MUTEX
- VOID MyFastMutexFun2(IN PVOID pContext)
- {
- PFAST_MUTEX pkMutex = (PFAST_MUTEX) pContext;
-
- ExAcquireFastMutex(pkMutex);
- KdPrint(("Enter MyFastMutexFun2\n"));
-
- KdPrint(("\tExecution...\n"));
- KeStallExecutionProcessor(2000);
- KdPrint(("Leave MyFastMutexFun2\n"));
-
- ExReleaseFastMutex(pkMutex);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
-
- VOID MyFastMutexFun1(IN PVOID pContext)
- {
- PFAST_MUTEX pkMutex = (PFAST_MUTEX) pContext;
-
- ExAcquireFastMutex(pkMutex);
- KdPrint(("Enter MyFastMutexFun1\n"));
-
- KdPrint(("\tExecution...\n"));
- KeStallExecutionProcessor(2000);
- KdPrint(("Leave MyFastMutexFun1\n"));
-
- ExReleaseFastMutex(pkMutex);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
-
- #pragma INITCODE
- VOID TestFastMutex()
- {
- HANDLE hMyThread1, hMyThread2;
- FAST_MUTEX fastMutex;
-
- ExInitializeFastMutex(&fastMutex);
-
- PsCreateSystemThread(&hMyThread1, 0, NULL, NtCurrentProcess(), NULL, MyFastMutexFun1, &fastMutex);
- PsCreateSystemThread(&hMyThread2, 0, NULL, NtCurrentProcess(), NULL, MyFastMutexFun2, &fastMutex);
- PVOID Pointer_Array[2];
- ObReferenceObjectByHandle(hMyThread1, 0, NULL, KernelMode, &Pointer_Array[0], NULL);
- ObReferenceObjectByHandle(hMyThread2, 0, NULL, KernelMode, &Pointer_Array[1], NULL);
-
-
- KeWaitForMultipleObjects(2, Pointer_Array, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
- ObDereferenceObject(Pointer_Array[0]);
- ObDereferenceObject(Pointer_Array[1]);
- KdPrint(("After KeWaitForMultipleObjects\n"));
- }
This message was edited 3 times. Last update was at 10/01/2011 11:08:57
沒有留言:
張貼留言