다음을 통해 공유


커널 디스패처 개체 소개

커널은 커널 디스패처 개체 또는 디스패처 개체라는 개체 형식 집합 을 정의합니다. 디스패처 개체에는 타이머 개체, 이벤트 개체, 세마포 개체, 뮤텍스 개체 및 스레드 개체가 포함됩니다.

드라이버는 IRQL에서 PASSIVE_LEVEL 실행하는 동안 디스패처 개체를 비비타 스레드 컨텍스트 내에서 동기화 메커니즘으로 사용할 수 있습니다.

Dispatcher 개체 상태

모든 커널 정의 디스패처 개체 형식에는 신호로 설정되거나 Not-Signaled로 설정된 상태가 있습니다.

하나 이상의 스레드가 KeWaitForSingleObject, KeWaitForMutexObject 또는 KeWaitForMultipleObjects를 호출하는 경우 스레드 그룹은 작업을 동기화할 수 있습니다. 이러한 함수는 디스패처 개체 포인터를 입력으로 사용하고 다른 루틴 또는 스레드가 하나 이상의 디스패처 개체를 Signaled 상태로 설정할 때까지 기다립니다.

스레드가 KeWaitForSingleObject 를 호출하여 디스패처 개체(또는 뮤텍스의 경우 KeWaitForMutexObject )를 기다리는 경우 디스패처 개체가 Signaled 상태로 설정될 때까지 스레드가 대기 상태로 전환됩니다. 스레드는 KeWaitForMultipleObjects 를 호출하여 디스패처 개체 집합이 Signaled로 설정될 때까지 또는 모두 대기할 수 있습니다.

디스패처 개체가 Signaled 상태로 설정될 때마다 커널은 해당 개체가 준비되기를 기다리는 모든 스레드의 상태를 변경합니다. (동기화 타이머 및 동기화 이벤트는 이 규칙의 예외입니다. 동기화 이벤트 또는 타이머에 신호를 받으면 대기 중인 스레드가 하나만 준비 상태로 설정됩니다. 자세한 내용은 타이머 개체 및 DPC 및이벤트 개체를 참조하세요.) 준비 상태의 스레드는 현재 런타임 스레드 우선 순위 및 해당 우선 순위 가 있는 모든 스레드에 대한 프로세서의 현재 가용성에 따라 실행되도록 예약됩니다.

드라이버는 언제 디스패처 개체를 기다릴 수 있나요?

일반적으로 드라이버는 다음 상황 중 하나 이상이 true인 경우에만 디스패처 개체가 설정될 때까지 기다릴 수 있습니다.

  • 드라이버가 비비타 스레드 컨텍스트에서 실행되고 있습니다.

    즉, 대기 상태가 될 스레드를 식별할 수 있습니다. 실제로 비공개 스레드 컨텍스트에서 실행되는 유일한 드라이버 루틴은 드라이버의 DriverEntry, AddDevice, Reinitialize언로드 루틴과 최고 수준의 드라이버의 디스패치 루틴뿐입니다. 이러한 모든 루틴은 시스템에서 직접 호출합니다.

  • 드라이버가 완전히 동기 I/O 요청을 수행하고 있습니다.

    즉, I/O 요청을 처리하는 동안 어떤 드라이버도 작업을 큐에 대기하지 않으며, 아래의 드라이버가 요청 처리를 완료할 때까지 드라이버가 반환되지 않습니다.

또한 드라이버가 IRQL 이상에서 실행되는 경우 대기 상태가 DISPATCH_LEVEL 입력할 수 없습니다.

이러한 제한 사항에 따라 다음 규칙을 사용해야 합니다.

  • 드라이버의 DriverEntry, AddDevice, Reinitialize언로드 루틴은 디스패처 개체를 기다릴 수 있습니다.

  • 최상위 드라이버의 디스패치 루틴은 디스패처 개체를 기다릴 수 있습니다.

  • 하위 수준 드라이버의 디스패치 루틴은 I/O 작업이 동기적(예: 만들기, 플러시, 종료 및 닫기 작업, 일부 디바이스 I/O 제어 작업, 일부 PnP 및 전원 작업)인 경우 디스패치 개체를 기다릴 수 있습니다.

  • 하위 수준 드라이버의 디스패치 루틴은 비동기 I/O 작업이 완료될 때까지 디스패처 개체를 기다릴 수 없습니다.

  • IRQL DISPATCH_LEVEL 이상에서 실행되는 드라이버 루틴은 디스패처 개체가 Signaled 상태로 설정될 때까지 기다리지 않아야 합니다.

  • 드라이버는 페이징 디바이스에서 전송 작업이 완료될 때까지 디스패처 개체가 Signaled 상태로 설정될 때까지 기다리지 않아야 합니다.

  • 읽기/쓰기 요청을 서비스하는 드라이버 디스패치 루틴은 일반적으로 디스패처 개체가 Signaled 상태로 설정될 때까지 기다릴 수 없습니다.

  • 디바이스 I/O 컨트롤 요청에 대한 디스패치 루틴은 I/O 컨트롤 코드의 전송 형식이 METHOD_BUFFERED 경우에만 디스패처 개체가 Signaled 상태로 설정될 때까지 기다릴 수 있습니다.

  • SCSI 미니포트 드라이버는 커널 디스패처 개체를 사용하면 안 됩니다. SCSI 미니포트 드라이버는 SCSI 포트 라이브러리 루틴만 호출해야 합니다.

다른 모든 표준 드라이버 루틴은 임의의 스레드 컨텍스트에서 실행됩니다. 즉, 대기 중인 작업을 처리하거나 디바이스 인터럽트를 처리하기 위해 드라이버 루틴이 호출될 때 현재 스레드가 발생합니다. 또한 대부분의 표준 드라이버 루틴은 DISPATCH_LEVEL 또는 DIRQL에서 디바이스 드라이버의 경우 발생된 IRQL에서 실행됩니다.

필요한 경우 드라이버는 드라이버의 다른 루틴(ISR 또는 SynchCritSection 루틴 제외)이 디스패처 개체를 Signaled 상태로 설정하고 Not-Signaled 상태로 다시 설정될 때까지 기다릴 수 있는 디바이스 전용 스레드를 만들 수 있습니다.

일반적인 지침으로, I/O 작업 중에 디바이스 상태 변경을 기다리는 동안 새 디바이스 드라이버가 50 마이크로초 이상 중단되어야 하는 경우가 많으면 디바이스 전용 스레드를 사용하여 드라이버를 구현하는 것이 좋습니다. 디바이스 드라이버가 최고 수준의 드라이버인 경우 시스템 작업자 스레드 를 사용하고 하나 이상의 작업자 스레드 콜백 루틴을 구현하는 것이 좋습니다. PsCreateSystemThreadDriver-Created 스레드를 사용하여 상호 잠긴 큐 관리를 참조하세요.