커널 디스패처 개체 소개
커널은 커널 디스패처 개체 또는 디스패처 개체라는 개체 형식 집합 을 정의합니다. 디스패처 개체에는 타이머 개체, 이벤트 개체, 세마포 개체, 뮤텍스 개체 및 스레드 개체가 포함됩니다.
드라이버는 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 마이크로초 이상 중단되어야 하는 경우가 많으면 디바이스 전용 스레드를 사용하여 드라이버를 구현하는 것이 좋습니다. 디바이스 드라이버가 최고 수준의 드라이버인 경우 시스템 작업자 스레드 를 사용하고 하나 이상의 작업자 스레드 콜백 루틴을 구현하는 것이 좋습니다. PsCreateSystemThread 및 Driver-Created 스레드를 사용하여 상호 잠긴 큐 관리를 참조하세요.