前言 :
在內核中還有另一種同步物件, 這就是信號燈. 和事件對向一樣, 信號燈在使用者模式下和核心模式下是完全統一的, 只不過操作方式不太一樣. 在使用者模式下, 信號燈物件用控制碼代表, 而在核心模式下, 信號燈物件用 KSEMAPHORE 資料結構表示.
核心模式下的信號燈 :
在使用信號燈物件前, 需要對信號燈物件進行初始化. 使用內核函式 KeInitializeSemaphore 對信號燈初始化, 其函式宣告如下 :
- Syntax :
- VOID KeInitializeSemaphore(
- __out PRKSEMAPHORE Semaphore,
- __in LONG Count,
- __in LONG Limit
- );
參數說明 :
* 參數 Semaphore : 這個參數獲得內核信號燈物件指標
* 參數 Count : 這個參數式初始化時的信號燈計數.
* 參數 Limit : 這個參數指名信號燈計數的上限.
KeReadStateSemaphore 函式可以讀取信號燈當前的計數. 釋放信號燈會增加信號燈計數, 它對應的內核函式是 KeReleaseSemaphore. 程式設計師可以用這個函式指定增量值. 獲得信號燈可以使用 KeWaitXXX 系列函式. 如果能獲得, 就將計數減一, 否則陷入等待, 下面程式碼展示了如何在驅動程式中使用信號燈物件 :
- Driver.cpp : 示範如何在核心模式下使用 信號燈
- VOID SemaphoreFun(IN PVOID pContext)
- {
-
- PKSEMAPHORE pkSemaphore = (PKSEMAPHORE) pContext;
- KdPrint(("Enter SemaphoreFun\n"));
- KeReleaseSemaphore(pkSemaphore, IO_NO_INCREMENT, 1, FALSE);
- LONG count = KeReadStateSemaphore(pkSemaphore);
-
- KdPrint(("Leave SemaphoreFun\n"));
-
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
-
- #pragma PAGEDCODE
- VOID TestSemaphore()
- {
- HANDLE hMyThread;
- KSEMAPHORE kSemaphore;
-
- KeInitializeSemaphore(&kSemaphore, 2, 2);
-
- LONG count = KeReadStateSemaphore(&kSemaphore);
- KdPrint(("The Semaphore count is %d\n", count));
-
- KeWaitForSingleObject(&kSemaphore, Executive, KernelMode, FALSE, NULL);
-
- count = KeReadStateSemaphore(&kSemaphore);
- KdPrint(("The Semaphore count is %d\n", count));
- NTSTATUS status = PsCreateSystemThread(&hMyThread, 0, NULL, NtCurrentProcess(), NULL, SemaphoreFun, &kSemaphore);
- }
底下是執行結果 :