自旋鎖我的理解就好比 小A,小B,小C,小D 同住一個屋子,可屋子只有一間茅房和一個馬桶。他們誰想"便"的時候誰就要把茅房的門鎖上,然後佔據馬桶,比如小A正在佔有,聚精會神,非常愜意。碰巧小 C此時甚急,但沒辦法,因為小A已經把門上了鎖。於是小B在門口急得打轉,即為"自旋"。注意這個"自旋"兩個字用的好,小B不是一看門被上鎖就回屋睡覺 去了,而是在門口"自旋"。... 最終的結果是小A開鎖,小B佔用。而且在開鎖閉鎖過程中動作乾淨利落,不容他人搶在前面。 如此周而復始...... 這裡的 小A,B,C,D 即為處理器,茅房的鎖即為自旋鎖。當其他處理器想訪問這個公用的資源的時候就要先擷取這個鎖。如果鎖被佔用,則自旋(迴圈)等待。 小A的聚精會神代表了IRQL為2,開關鎖動作快表示為原子操作。 ---------------------------------------------------------- 不知道我理解的對還是不對,可能這樣舉例有些不恰當。有理解不對之處希望指點一二,以免誤入歧途,悔之晚矣。 ---------------------------------------------------------- 寫了個測試程式測試了一下: KSPIN_LOCK spinlock; NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNICODE_STRING DeviceName; PDEVICE_OBJECT DeviceObject; HANDLE ThreadHandle; KIRQL oldirql; KIRQL irql; ULONG Processor; ULONG i; DeviceObject = NULL; RtlInitUnicodeString( &DeviceName, deviceNameBuffer ); Status = IoCreateDevice( DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject ); if ( !NT_SUCCESS(Status) ) { return Status; } DriverObject->DriverUnload = DriverUnload; KeInitializeSpinLock( &spinlock ); // (2) PsCreateSystemThread( &ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadRoutine, NULL ); i = 10000; KeAcquireSpinLock( &spinlock, &oldirql ); while (i--) { __asm nop irql = KeGetCurrentIrql(); Processor = KeGetCurrentProcessorNumber(); KdPrint(( " [%d] CurrentIrql:\t%d", Processor, irql )); } KeReleaseSpinLock( &spinlock, oldirql ); return Status; } VOID ThreadRoutine( IN PVOID StartContext ) { KIRQL oldirql; KIRQL irql; ULONG Processor; ULONG i; i = 10000; KeAcquireSpinLock( &spinlock, &oldirql ); // (1) while (i--) { __asm nop irql = KeGetCurrentIrql(); Processor = KeGetCurrentProcessorNumber(); KdPrint(( "**[%d] CurrentIrql:\t%d", Processor, irql )); } KeReleaseSpinLock( &spinlock, oldirql ); // (1) } --------------------------------------------------------------------------------- 首先說明一下我是雙核系統,如果是單核的話我想進入自旋鎖之後IRQL已經提高到 DPC 層級,第二個線程就跑不起來了。如果他神奇的跑了起來,那一定會發生死結。 分幾種情況測試: 1、就是上邊的代碼測試 先抓到鎖的先跑,後抓到鎖的後跑。並且被鎖的期間的IRQL 為 DPC 層級。 2、去掉 標記 (1) 的兩行 結果是兩個線程同時跑,一個占處理器 [0] 一個占處理器 [1] 上鎖的那個 IRQL 層級是 DPC 級。 沒上鎖的IRQL為 0 即 自旋鎖 並不影響其他處理器的正常運行。除非其他處理器也想獲得這個鎖。 3、去掉 標記 (2) 的一行(spinlock 是全域變數) 和 1 的結果相同,因為全域變數預設是初始化為0的。 |