一.用户模式的信号灯
信号灯内部有个计数器,可以理解信号灯内部有N个灯泡,如果有一个灯泡亮着,就代表信号灯处于激发状态,如果全部熄灭,就代表信号灯处于未激发状态。
创建信号灯:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,// pointer to security attributes
LONG lInitialCount, // initial count
LONG lMaximumCount, // maximum count
LPCTSTR lpName // pointer to semaphore-object name
);
增加信号灯的计数器:
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // handle to the semaphore object
LONG lReleaseCount, // amount to add to current count
LPLONG lpPreviousCount // address of previous count
);
对信号灯执行一次等待操作,就会减少一个计数,就相当于熄灭一个灯泡。当计数为0时,也就是所有灯泡都熄灭时,当前线程进入睡眠状态,直到信号灯变成激发状态或者超时。
// Semaphore-ThreadSynchronization.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> void Sub_1(); HANDLE __SemaphoreHandle = NULL; int main() { /* HANDLE SemaphoreHandle = NULL; HANDLE ThreadHandle = NULL; SemaphoreHandle = CreateSemaphore(NULL, 2, 2, NULL); //创建两个亮着的灯泡 WaitForSingleObject(SemaphoreHandle, INFINITE); //熄灭一盏灯 ReleaseSemaphore( SemaphoreHandle, //信号量的句柄 1, //增加个数 NULL); //用来传出先前的资源计数,设为NULL表示不需要传出 WaitForSingleObject(SemaphoreHandle, INFINITE); WaitForSingleObject(SemaphoreHandle, INFINITE); */ __SemaphoreHandle = CreateSemaphore( NULL, //安全结构 2, //初始资源数量 2, //最大并发数量 NULL); //匿名信号量 Sub_1(); printf("Input AnyKey To Exit\r\n"); getchar(); return 0; } void Sub_1() { WaitForSingleObject(__SemaphoreHandle, INFINITE); printf("Sub_1()\r\n"); Sub_1(); }
二.内核模式下的信号灯
在内核模式下,信号灯对象用KSEMAPHORE数据结构表示。在使用信号灯对象钱,需要对其进行初始化(KeInitializeSemaphore)
KeReadStateSemaphore函数可以读取信号灯当前计数。
释放信号灯会增加信号灯计数,对应内核函数KeReleaseSemaphore函数。
#include "KSemaphore.h" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath) { NTSTATUS Status = STATUS_SUCCESS; PDEVICE_OBJECT DeviceObject = NULL; DriverObject->DriverUnload = DriverUnload; SeCreateSemaphore(); return Status; } VOID DriverUnload(PDRIVER_OBJECT DriverObject) { DbgPrint("DriverUnload()\r\n"); } VOID SeCreateSemaphore() { HANDLE ThreadHandle = NULL; KSEMAPHORE Semaphore; ULONG Count = 0; PVOID ThreadObject = NULL; KeInitializeSemaphore(&Semaphore, 2, 2); Count = KeReadStateSemaphore(&Semaphore); DbgPrint("Semaphore Count:%d\r\n", Count); KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL); Count = KeReadStateSemaphore(&Semaphore); DbgPrint("Semaphore Count:%d\r\n", Count); KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL); PsCreateSystemThread(&ThreadHandle, 0, NULL, NULL, NULL, ThreadProcedure, &Semaphore); KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL); ObReferenceObjectByHandle(ThreadHandle, 0, NULL, KernelMode, &ThreadObject, NULL); KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL); ZwClose(ThreadHandle); } VOID ThreadProcedure(PVOID ParameterData) { PKSEMAPHORE Semaphore = (PKSEMAPHORE)ParameterData; KeReleaseSemaphore(Semaphore, IO_NO_INCREMENT, 1, FALSE); PsTerminateSystemThread(STATUS_SUCCESS); }