2017-11-07 12 views
0

한 디스패치 루틴 내부를 회전 우리는 다음과 같은 코드가 있습니다 때 우리가 있도록Windows 드라이버, 잠금 수집 및 조건 테스트

KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceExtension->SpinLock, &LockHandle); 

//... 

DeviceExtension->Flag = FALSE; 
KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle); 

: 우리는 다음과 같은 코드가 다른 디스패치 루틴 내부

if (DeviceExtension->Flag) 
{ 
    KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceExtension->SpinLock, &LockHandle); 

    //... when we will enter here, DeviceExtension->Flag can already be set to FALSE. 

    KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle); 
} 

을 첫 번째 디스패치 루틴 내에서 스핀 록을 획득하려면 DeviceExtension->Flag을 두 번째 루틴으로 이미 FALSE으로 설정할 수 있습니다. 해결책은 스핀 록을 획득 한 다음 DeviceExtension->Flag을 확인하는 것입니다. 그러나 DeviceExtension->Flag은 FALSE 일 수 있으며 스핀 잠금 획득은이 경우 매우 무겁습니다.

특히 커널 모드에서 멀티 스레딩에 익숙하지 않습니다. 나는 그 질문이 어리 석다는 것을 알고 있지만, 나는 길을 잃었다. 이 경우 올바른 해결책은 무엇입니까? 고맙습니다.

+1

방금해야 할 것 같네요에서 호출해야한다는 주장 [재확인 잠금 (https://en.wikipedia.org/wiki/Double-checked_locking)? 첫 번째 스 니펫에서 잠금 후 플래그를 다시 확인하고 false이면 해제하고 중단합니다. – Blorgbeard

+0

"프로그램 된대로"작동하고있는 것으로 보입니다. 두 번째 코드 단편은 FALSE로 설정 한 다음 그대로 유지합니다. 스핀 락이 당신을 보장하고있는 유일한 방법은'KeAcquireInStackQueuedSpinLockAtDpcLevel'와'KeReleaseInStackQueuedSpinLockFromDpcLevel'에 대한 호출 사이의 "동기화 된"접근 일 것입니다. 아마도 두 번째 루틴의 끝에 플래그를 다시 TRUE로 설정하고 싶습니까? – rogerdpack

+0

아니요, 실제로이 플래그는 장치가 제거되어야 함을 나타내므로 한 방향으로 작동합니다. – igntec

답변

1

이 플래그는 장치가 제거되는 것을 나타냅니다, 그래서 당신이 장치 확장 대신 bool Flag

에서 EX_RUNDOWN_REF RunRef; 회원이 필요한이 특별이

Run-Down Protection 존재하기위한 하나의 방법

를 작동

ExInitializeRundownProtection(&RunRef); 
으로 초기화하십시오. (210)

당신은 장치가 아직 당신이 할 필요가 제거되지 않은 경우에만, 어떤 작업을 할 필요가있을 때 :

if (ExAcquireRundownProtection(&DeviceExtension->RunRef)) 
{ 
    // do something 
    ExReleaseRundownProtection(&DeviceExtension->RunRef) 
} 

IRP_MN_REMOVE_DEVICE 핸들러에 전화 할 필요를

ExWaitForRundownProtectionRelease(&DeviceExtension->RunRef); 

중요한 참고 -에서에도 불구하고 msdn은 IRQL <= APC_LEVELExAcquireRundownProtectionExReleaseRundownProtection을 호출해야한다고 말하면 이것은 틀렸고 실수였습니다. ExAcquireRundownProtection 간단히 말하자면 점 RunRef에 메모리가있는 연동 작업을 수행합니다. 비 페이징 풀에있는 경우이 루틴을 IRQL이라고 부를 수 있습니다. 장치 확장이 비 페이징 풀에 있습니다. ExReleaseRundownProtection을 추가로 KeSetEvent으로 전화 할 수 있습니다. 대기FALSE으로 설정됩니다. 그 결과로 IRQL <= DISPATCH_LEVEL에서 실행될 수 있습니다. ExReleaseRundownProtection 우리는 IoCompletion 루틴 (DISPATCH_LEVEL보다 작거나 같음 IRQL에서 실행 됨)에서 일반적인 호출을하므로 여기 모두 괜찮습니다. 물론

ExWaitForRundownProtectionRelease 우리가 기다릴 수 있습니다 여기에 있기 때문에 <= APC_LEVEL에서 호출하지만, PNP는 관리자가 IRQLPASSIVE_LEVELIRP_MN_REMOVE_DEVICE를 전송해야 - 당신의 여기가 사용할 수 있습니다 여기에 물론


그래서 다시 한번 더 확인을 할 Remove Locks 런 다운 보호와 거의 동일합니다. 간단하게 런 다운 보호 - 더 많은 새 API 및 더 나은 설계/구현 잠금 제거 비교.그러나 IoReleaseRemoveLockIoReleaseRemoveLock에 대한 설명서에 올바르게 IRQL <= DISPATCH_LEVEL가 있어야하며 IoReleaseRemoveLockAndWaitPASSIVE_LEVEL