다음을 통해 공유


IoTimer 루틴 사용

연결된 디바이스 개체에 대한 타이머를 사용하는 동안 IoTimer 루틴은 초당 약 한 번 호출됩니다. 그러나 각 IoTimer 루틴이 호출되는 간격은 시스템 클록의 해상도에 따라 달라지므로 IoTimer 루틴이 1초 경계에서 정확하게 호출된다고 가정하지 마세요.

참고 모든 DPC 루틴과 마찬가지로 IoTimer 루틴은 IRQL = DISPATCH_LEVEL 호출됩니다. DPC 루틴이 실행되는 동안 모든 스레드는 동일한 프로세서에서 실행되지 않습니다. 드라이버 개발자는 가능한 한 짧은 시간 동안 실행되도록 IoTimer 루틴을 신중하게 디자인해야 합니다.

아마도 IoTimer 루틴의 가장 일반적인 용도는 IRP에 대한 디바이스 I/O 작업의 시간 초과입니다. 디바이스 드라이버 내에서 실행 중인 타이머로 IoTimer 루틴을 사용하는 다음 시나리오를 고려합니다.

  1. 디바이스가 시작되면 드라이버는 디바이스 확장에서 타이머 카운터를 -1로 초기화하여 현재 디바이스 I/O 작업이 없음을 나타내고 STATUS_SUCCESS 반환하기 직전에 IoStartTimer를 호출합니다.

    IoTimer 루틴을 호출할 때마다 타이머 카운터가 -1인지 확인하고, 이 경우 컨트롤을 반환합니다.

  2. 드라이버의 StartIo 루틴은 디바이스 확장의 타이머 카운터를 상한값으로 초기화하고 IoTimer 루틴이 방금 실행된 경우 추가 초를 추가합니다. 그런 다음 KeSynchronizeExecution 을 사용하여 현재 IRP에서 요청한 작업에 대한 물리적 디바이스를 프로그래밍하는 SynchCritSection_1 루틴을 호출합니다.

  3. 드라이버의 ISR은 드라이버의 DpcForIsr 루틴 또는 CustomDpc 루틴을 큐에 추가하기 전에 타이머 카운터를 -1로 다시 설정합니다.

  4. IoTimer 루틴을 호출할 때마다 ISR에 의해 타이머 카운터가 -1로 다시 설정되었는지 확인하고, 이 경우 컨트롤을 반환합니다. 그렇지 않은 경우 IoTimer 루틴은 KeSynchronizeExecution 을 사용하여 SynchCritSection_2 루틴을 호출하여 드라이버에서 결정한 시간(초)으로 타이머 카운터를 조정합니다.

  5. SynchCritSection_2 루틴은 현재 요청 시간이 아직 초과되지 않은 한 TRUEIoTimer 루틴으로 반환합니다. 타이머 카운터가 0으로 설정되면 SynchCritSection_2 루틴은 타이머 카운터를 드라이버에서 결정한 초기화 시간 제한 값으로 다시 설정하고, 컨텍스트 영역에서 자체(및 DpcForIsr의 경우)에 대해 다시 설정 예상 플래그를 설정하고, 디바이스를 다시 설정하려고 시도하고, TRUE를 반환합니다.

    SynchCritSection_2 루틴은 다시 설정 작업이 디바이스에서 시간 초과된 경우 FALSE를 반환할 때 다시 호출됩니다. 다시 설정이 성공하면 DpcForIsr 루틴은 디바이스가 다시 설정 예상 플래그에서 다시 설정되었는지 확인하고 요청을 다시 시도하여 2단계에 설명된 대로 StartIo 루틴의 작업을 반복합니다.

  6. SynchCritSection_2 루틴이 FALSE를 반환하는 경우 IoTimer 루틴은 초기화 시도가 이미 실패했기 때문에 물리적 디바이스가 알 수 없는 상태라고 가정합니다. 이러한 경우 IoTimer 루틴은 CustomDpc 루틴을 큐에 대기하고 를 반환합니다. 이 CustomDpc 루틴은 디바이스 I/O 오류를 기록하고, IoStartNextPacket을 호출하고, 현재 IRP에 실패하고, 를 반환합니다.

이 디바이스 드라이버의 ISR이 3단계에 설명된 대로 공유 타이머 카운터를 -1로 다시 설정하는 경우 드라이버의 DpcForIsr 루틴은 현재 IRP의 인터럽트 기반 I/O 처리를 완료합니다. 재설정 타이머 카운터는 이 디바이스 I/O 작업이 시간 초과되지 않았으므로 IoTimer 루틴에서 타이머 카운터를 변경할 필요가 없음을 나타냅니다.

대부분의 경우 이전 SynchCritSection_2 루틴은 단순히 타이머 카운터를 감소합니다. SynchCritSection_2 루틴은 타이머 카운터가 0으로 이동했을 때 표시되는 현재 I/O 작업 시간이 초과된 경우에만 디바이스를 다시 설정하려고 시도합니다. 디바이스를 다시 설정하려는 시도가 이미 실패한 경우에만 SynchCritSection_2 루틴이 IoTimer 루틴에 FALSE를 반환합니다.

따라서 이전 IoTimer 루틴과 해당 도우미 SynchCritSection_2 루틴은 모두 정상적인 상황에서 실행하는 데 시간이 거의 걸리지 않습니다. 이러한 방식으로 IoTimer 루틴을 사용하면 디바이스 드라이버는 필요한 경우 유효한 각 디바이스 I/O 요청을 다시 시도하도록 하고, 수정할 수 없는 하드웨어 오류로 인해 IRP가 충족되지 않는 경우에만 CustomDpc 루틴이 IRP에 실패하도록 합니다. 또한 드라이버는 실행 시간에 매우 적은 비용으로 이 기능을 제공합니다.

이전 시나리오의 단순성은 한 번에 하나의 작업만 수행하는 디바이스와 일반적으로 I/O 작업과 겹치지 않는 드라이버에 따라 달라집니다. 겹치는 디바이스 I/O 작업을 수행하는 드라이버 또는 IoTimer 루틴을 사용하여 두 개 이상의 낮은 드라이버 체인으로 전송된 드라이버 할당 IR 집합을 시간 초과하는 상위 수준 드라이버는 관리해야 하는 더 복잡한 시간 제한 시나리오가 있습니다.