타이머 개체 사용
다음 그림에서는 알림 타이머를 사용하여 작업에 대한 시간 제한 간격을 설정한 다음 다른 드라이버 루틴이 I/O 요청을 처리하는 동안 기다리는 방법을 보여 줍니다.
이전 그림과 같이 드라이버는 타이머 개체에 대한 스토리지를 제공해야 하며, 이 스토리지에 대한 포인터를 사용하여 KeInitializeTimer 를 호출하여 초기화해야 합니다. 드라이버는 일반적으로 AddDevice 루틴에서 이 호출을 수행합니다.
드라이버에서 만든 스레드 또는 동기 I/O 작업을 요청하는 스레드와 같은 특정 스레드의 컨텍스트 내에서 드라이버는 이전 그림과 같이 타이머 개체를 기다릴 수 있습니다.
스레드는 타이머 개체에 대한 포인터와 100나노초 단위로 표현된 지정된 DueTime 값을 사용하여 KeSetTimer를 호출합니다. DueTime에 대한 양수 값은 타이머 개체를 커널의 타이머 큐에서 제거하고 Signaled 상태로 설정해야 하는 절대 시간을 지정합니다. DueTime의 음수 값은 현재 시스템 시간을 기준으로 간격을 지정합니다.
스레드(또는 시스템 스레드에서 실행되는 드라이버 루틴)는 CustomTimerDpc 루틴을 큐에 대기하는 대신 타이머 개체에서 대기하는 경우 KeSetTimer를 호출할 때 DPC 개체에 대한 NULL 포인터(CustomTimerDpc 루틴에 타이머 및 DPC 개체를 사용하는 그림의 이전 그림에 표시됨)를 전달합니다.
스레드는 타이머 개체에 대한 포인터를 사용하여 KeWaitForSingleObject 를 호출하여 타이머 개체가 커널의 타이머 큐에 있는 동안 스레드를 대기 상태로 만듭니다.
지정된 DueTime 이 만료됩니다.
커널은 타이머 개체를 큐에서 제거하고, 신호됨 상태로 설정하고, 스레드 상태를 대기 중에서 준비 상태로 변경합니다.
커널은 프로세서를 사용할 수 있는 즉시 실행하기 위해 스레드를 디스패치합니다. 즉, 우선 순위가 높은 다른 스레드가 현재 준비 상태이며 더 높은 IRQL에서 실행할 커널 모드 루틴이 없습니다.
IRQL >= DISPATCH_LEVEL 실행되는 드라이버 루틴은 연결된 DPC 개체와 타이머 개체를 사용하여 드라이버 제공 CustomTimerDpc 루틴을 큐에 대기시켜 요청을 제한할 수 있습니다. 비비타적 스레드 컨텍스트 내에서 실행되는 드라이버 루틴만 이전 그림과 같이 타이머 개체에서 0이 아닌 간격을 기다릴 수 있습니다.
다른 모든 스레드와 마찬가지로 드라이버에서 만든 스레드는 디스패처 개체이기도 한 커널 스레드 개체로 표시됩니다. 따라서 드라이버에서 만든 스레드가 타이머 개체를 사용하여 지정된 간격 동안 자발적으로 대기 상태로 전환할 필요가 없습니다. 대신 스레드는 호출자 제공 간격으로 KeDelayExecutionThread 를 호출할 수 있습니다. 이 기술에 대한 자세한 내용은 디바이스 폴링을 참조하세요.
DriverEntry, Reinitialize 및 언로드 루틴도 시스템 스레드 컨텍스트에서 실행되므로 드라이버는 초기화 타이머 개체 또는 초기화하거나 언로드하는 동안 KeDelayExecutionThread를 사용하여 KeWaitForSingleObject를 호출할 수 있습니다. 디바이스 드라이버는 초기화 중에 디바이스가 상태를 업데이트할 때까지 기다려야 하는 경우 매우 짧은 간격(바람직하게는 50 마이크로초 미만)으로 KeStallExecutionProcessor 를 호출할 수 있습니다.
그러나 상위 수준의 드라이버는 일반적으로 타이머 개체를 사용하는 대신 DriverEntry 에서 다른 동기화 메커니즘을 사용하고 루틴을 다시 초기화 합니다. 상위 수준 드라이버는 항상 특정 유형 또는 디바이스 유형의 하위 수준 드라이버보다 계층화되도록 설계되어야 합니다. 따라서 더 높은 수준의 드라이버는 타이머 개체에서 기다리거나 KeDelayExecutionThread 를 호출하는 경우 로드 속도가 느려지는 경향이 있습니다. 이러한 드라이버는 이를 지원하는 가장 느린 디바이스를 수용할 수 있을 만큼 간격을 기다려야 하기 때문입니다. 또한 "안전"하지만 이러한 대기에 대한 최소 간격은 결정하기가 매우 어렵습니다.
마찬가지로 PnP 드라이버는 다른 작업이 발생할 때까지 기다리지 말고 대신 PnP 관리자의 알림 메커니즘을 사용해야 합니다.