공유 상태 정보에 액세스
상태를 유지하는 SynchCritSection 루틴을 디자인하고 작성하려면 다음 일반 지침을 사용합니다.
ISR도 액세스하는 데이터에 액세스하려면 드라이버 루틴이 SynchCritSection 루틴을 호출해야 합니다. 중요하지 않은 섹션 코드는 중단될 수 있습니다. ISRQL에서 실행되고 스핀 잠금(KeAcquireSpinLock)을 획득하면 IRQL이 DISPATCH_LEVEL 발생하므로 ISR이 액세스하는 데이터를 보호하기 위해 스핀 잠금을 획득하는 것만으로는 충분하지 않습니다. 따라서 인터럽트는 현재 프로세서에서 ISR을 호출할 수 있습니다.
개별 상태 변수 집합에 대한 상태 정보 책임을 유지하는 각 SynchCritSection 루틴을 제공합니다. 즉, 겹치는 상태 정보를 유지하는 SynchCritSection 루틴을 작성하지 않습니다.
이렇게 하면 동일한 상태에 동시에 액세스하려는 SynchCritSection 루틴(및 ISR) 간의 경합 및 경합 조건이 방지됩니다.
또한 하나의 SynchCritSection 루틴이 컨트롤을 반환하기 위해 동일한 상태 정보 중 일부를 업데이트하는 다른 루틴을 기다릴 필요가 없으므로 각 SynchCritSection 루틴은 가능한 한 빨리 컨트롤을 반환합니다.
실제로 유용한 작업을 수행하는 것보다 수행할 작업을 결정하기 위해 조건을 더 많이 테스트하는 단일 범용 SynchCritSection 루틴을 작성하지 마세요. 반면에 각 은 단일 바이트 상태 정보만 업데이트하므로 조건문을 실행하지 않는 많은 SynchCritSection 루틴이 없으면 안 됩니다.
모든 SynchCritSection 루틴을 실행하면 드라이버의 ISR이 실행되지 않으므로 모든 SynchCritSection 루틴은 가능한 한 빨리 컨트롤을 반환해야 합니다.
다음은 디바이스 확장에서 타이머 카운터를 유지 관리하는 기술입니다. 드라이버가 카운터를 사용하여 I/O 작업 시간이 초과되었는지 확인한다고 가정합니다. 또한 드라이버가 I/O 작업과 겹치지 않는다고 가정합니다.
드라이버의 StartIo 루틴은 타이머 카운터를 각 I/O 요청에 대한 초기 값으로 초기화합니다. 그런 다음, IoTimer 루틴이 컨트롤을 방금 반환한 경우 드라이버가 디바이스 시간 제한 값에 두 번째 를 추가합니다.
드라이버의 ISR은 이 타이머 카운터를 빼기로 설정해야 합니다.
드라이버의 IoTimer 루틴은 초당 한 번 호출되어 시간 카운터를 읽고 ISR이 이미 빼기로 설정했는지 여부를 확인합니다. 그렇지 않은 경우 IoTimer 루틴은 KeSynchronizeExecution 을 사용하여 SynchCritSection_1 루틴을 호출하여 카운터를 감소시킵니다.
요청 시간이 초과되었음을 나타내는 카운터가 0으로 이동하면 SynchCritSection_1 루틴은 SynchCritSection_2 루틴을 호출하여 디바이스 재설정 작업을 프로그래밍합니다. 카운터가 1을 뺀 값이면 IoTimer 루틴이 단순히 반환됩니다.
드라이버의 DpcForIsr 루틴이 부분 전송 작업을 시작하기 위해 디바이스를 다시 프로그래밍해야 하는 경우 StartIo 루틴처럼 타이머 카운터를 다시 초기화해야 합니다.
또한 DpcForIsr 루틴은 KeSynchronizeExecution을 사용하여 SynchCritSection_2 루틴 또는 SynchCritSection_3 루틴을 호출하여 디바이스를 다른 전송 작업을 위해 프로그래밍해야 합니다.
이 시나리오에서 드라이버에는 각각 불연속적이고 특정한 책임이 있는 둘 이상의 SynchCritSection 루틴이 있습니다. 하나는 타이머 카운터를 유지 관리하고, 하나 이상의 다른 하나는 디바이스를 프로그래밍합니다. 각 SynchCritSection 루틴은 단일 개별 작업을 수행하므로 컨트롤을 빠르게 반환할 수 있습니다.
드라이버에는 드라이버의 ISR과 함께 타이머 카운터에 대한 상태를 유지하는 단일 SynchCritSection_1 루틴이 있습니다. 따라서 여러 SynchCritSection 루틴과 ISR 간에 타이머 카운터에 대한 액세스에 대한 경합이 없습니다.