Windows Driver Model >> Pascal >> Synchronization
Mutex
參考資訊:
1. Source Code
Mutex是一個互斥的機制,有點類似Spin Lock,當有CPU取得Mutex後,其餘CPU會處於Wait狀態,而相較於Spin Lock,Mutex並不會讓CPU處於忙碌的狀態,也不會提升到DISPATCH_LEVEL,是一個相當適合用來做序列化的機制,使用步驟如下:
1. KeInitializeMutex()
2. KeWaitForSingleObject()
3. KeReleaseMutex()
main.pas
unit main; interface uses DDDK; const MAX_THREAD = 3; DEV_NAME = '\Device\MyDriver'; SYM_NAME = '\DosDevices\MyDriver'; function _DriverEntry(pOurDriver:PDRIVER_OBJECT; pOurRegistry:PUNICODE_STRING):NTSTATUS; stdcall; implementation var myMutex: KMUTEX; pNextDevice: PDEVICE_OBJECT; procedure MyThread(pParam:Pointer); stdcall; var tt: LARGE_INTEGER; begin tt.HighPart:= tt.HighPart or -1; tt.LowPart:= ULONG(-10000000); DbgPrint('Thread%d, Acquiring Mutex', [ULONG(pParam)]); KeWaitForSingleObject(@myMutex, Executive, KernelMode, FALSE, Nil); DbgPrint('Thread%d, Acquired Mutex', [ULONG(pParam)]); DbgPrint('Thread%d, Sleeping', [ULONG(pParam)]); KeDelayExecutionThread(KernelMode, FALSE, @tt); DbgPrint('Thread%d, Releasing Mutex', [ULONG(pParam)]); KeReleaseMutex(@myMutex, FALSE); DbgPrint('Thread%d, Released Mutex', [ULONG(pParam)]); PsTerminateSystemThread(STATUS_SUCCESS); end; procedure Unload(pOurDriver:PDRIVER_OBJECT); stdcall; begin end; function IrpPnp(pOurDevice:PDEVICE_OBJECT; pIrp:PIRP):NTSTATUS; stdcall; var psk: PIO_STACK_LOCATION; suSymName: UNICODE_STRING; begin psk:= IoGetCurrentIrpStackLocation(pIrp); if psk^.MinorFunction = IRP_MN_REMOVE_DEVICE then begin RtlInitUnicodeString(@suSymName, SYM_NAME); IoDetachDevice(pNextDevice); IoDeleteDevice(pOurDevice); IoDeleteSymbolicLink(@suSymName); end; IoSkipCurrentIrpStackLocation(pIrp); Result:= IoCallDriver(pNextDevice, pIrp); end; function AddDevice(pOurDriver:PDRIVER_OBJECT; pPhyDevice:PDEVICE_OBJECT):NTSTATUS; stdcall; var suDevName: UNICODE_STRING; suSymName: UNICODE_STRING; pOurDevice: PDEVICE_OBJECT; begin RtlInitUnicodeString(@suDevName, DEV_NAME); RtlInitUnicodeString(@suSymName, SYM_NAME); IoCreateDevice(pOurDriver, 0, @suDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, pOurDevice); pNextDevice:= IoAttachDeviceToDeviceStack(pOurDevice, pPhyDevice); pOurDevice^.Flags:= pOurDevice^.Flags or DO_BUFFERED_IO; pOurDevice^.Flags:= pOurDevice^.Flags and not DO_DEVICE_INITIALIZING; Result:= IoCreateSymbolicLink(@suSymName, @suDevName); end; function _DriverEntry(pOurDriver:PDRIVER_OBJECT; pOurRegistry:PUNICODE_STRING):NTSTATUS; stdcall; var cc: ULONG; hThread: Handle; status: NTSTATUS; begin pOurDriver^.MajorFunction[IRP_MJ_PNP]:= @IrpPnp; pOurDriver^.DriverExtension^.AddDevice:=@AddDevice; pOurDriver^.DriverUnload:=@Unload; KeInitializeMutex(@myMutex, 0); for cc:=0 to (MAX_THREAD-1) do begin status:= PsCreateSystemThread(@hThread, THREAD_ALL_ACCESS, Nil, Handle(-1), Nil, MyThread, Pointer(cc)); if NT_SUCCESS(status) then begin ZwClose(hThread); end; end; Result:=STATUS_SUCCESS; end; end.
DriverEntry()產生3個Thread,每個Thread會嘗試取得Mutex,一旦取得Mutex後,會延遲一秒後才釋放Mutex,達到一次只能有一個CPU執行的效果
結果