Driver-Created 스레드를 사용하여 인터로킹된 큐 관리
새 드라이버는 이 섹션에 설명된 메서드를 기본 설정으로 취소 안전 IRP 큐 프레임워크를 사용해야 합니다.
시스템 플로피 컨트롤러 드라이버와 마찬가지로 StartIo 루틴이 아닌 디바이스 전용 스레드가 있는 드라이버는 일반적으로 이중으로 연결된 연결된 큐에서 자체 IRP 큐를 관리합니다. 드라이버의 스레드는 디바이스에서 수행해야 할 작업이 있을 때 연결된 큐에서 IRP를 가져옵니다.
일반적으로 드라이버는 스레드와 다른 드라이버 루틴 간에 공유되는 모든 리소스에 대한 스레드와의 동기화를 관리해야 합니다. 또한 드라이버는 드라이버에서 만든 스레드에 IRP가 큐에 대기 중임을 알리는 방법이 있어야 합니다. 일반적으로 스레드는 IRP를 인터로킹된 큐에 삽입한 후 드라이버의 Dispatch 루틴이 디스패처 개체를 Signaled 상태로 설정할 때까지 디바이스 확장에 저장된 디스패처 개체에서 대기합니다.
드라이버의 디스패치 루틴이 호출되면 각각 입력 IRP의 I/O 스택 위치에서 매개 변수를 확인하고 유효한 경우 추가 처리를 위해 요청을 큐에 대기합니다. 드라이버 전용 스레드에 큐에 대기 중인 각 IRP에 대해 디스패치 루틴은 ExInterlockedInsertXxxList를 호출하기 전에 스레드가 해당 IRP를 처리하는 데 필요한 컨텍스트를 설정해야 합니다. 각 IRP에서 드라이버의 I/O 스택 위치는 스레드가 큐에서 각 IRP를 제거하므로 드라이버가 스레드와 컨텍스트 정보를 공유할 수 있는 대상 디바이스 개체의 디바이스 확장에 대한 드라이버 스레드 액세스를 제공합니다.
취소 가능한 IRP를 큐에 대기하는 드라이버는 취소 루틴을 구현해야 합니다. IRP는 비동기적으로 취소되므로 드라이버가 발생할 수 있는 경합 조건을 피해야 합니다. IRP 취소 동기화를 참조하세요. IRP 취소 및 이를 방지하기 위한 기술 취소와 관련된 경합 조건에 대한 자세한 내용은 IRP 취소를 참조하세요.
드라이버에서 만든 스레드는 IRQL = PASSIVE_LEVEL 및 드라이버가 PsCreateSystemThread라고 할 때 이전에 설정한 기본 런타임 우선 순위에서 실행됩니다. ExInterlockedRemoveHeadList에 대한 스레드의 호출은 IRP가 드라이버의 내부 큐에서 제거되는 동안 IRQL이 현재 프로세서에서 DISPATCH_LEVEL 발생합니다. 원래 IRQL은 이 호출에서 반환될 때 PASSIVE_LEVEL 복원됩니다.
모든 드라이버 스레드(또는 드라이버 제공 작업자-스레드 콜백)는 실행되는 IRQL을 신중하게 관리해야 합니다. 다음 예를 살펴보십시오.
시스템 스레드는 일반적으로 IRQL = PASSIVE_LEVEL 실행되므로 드라이버 스레드가 커널 정의 디스패처 개체가 신호 상태로 설정될 때까지 기다릴 수 있습니다.
예를 들어 디바이스 전용 스레드는 다른 드라이버가 이벤트를 충족하고 스레드가 IoBuildSynchronousFsdRequest로 설정하는 일부 부분 전송 IRP를 완료할 때까지 기다릴 수 있습니다.
그러나 이러한 디바이스 전용 스레드는 특정 지원 루틴을 호출하기 전에 현재 프로세서에서 IRQL을 발생시켜야 합니다.
예를 들어 드라이버가 DMA를 사용하는 경우 디바이스 전용 스레드는 KeRaiseIrql 및 KeLowerIrql 호출 사이에 AllocateAdapterChannel 및 FreeAdapterChannel에 대한 호출을 중첩해야 합니다. 이러한 루틴과 DMA 작업에 대한 특정 기타 지원 루틴은 IRQL = DISPATCH_LEVEL 호출되어야 하기 때문입니다.
StartIo 루틴은 DISPATCH_LEVEL 실행되므로 DMA를 사용하는 드라이버는 StartIo 루틴에서 KeXxxIrql 루틴을 호출할 필요가 없습니다.
드라이버에서 만든 스레드는 IRQL = PASSIVE_LEVEL 비비트 스레드 컨텍스트(자체)에서 실행되기 때문에 페이저블 메모리에 액세스할 수 있지만 다른 많은 표준 드라이버 루틴은 IRQL >= DISPATCH_LEVEL 실행됩니다. 드라이버에서 만든 스레드가 이러한 루틴에서 액세스할 수 있는 메모리를 할당하는 경우 페이지가 없는 풀에서 메모리를 할당해야 합니다. 예를 들어 디바이스 전용 스레드가 드라이버의 ISR 또는 SynchCritSection, AdapterControl, AdapterListControl, ControllerControl, DpcForIsr, CustomDpc, IoTimer, CustomTimerDpc 또는 상위 수준 드라이버인 IoCompletion 루틴에서 나중에 액세스할 버퍼를 할당하는 경우 스레드 할당 메모리는 페이징할 수 없습니다.
드라이버가 디바이스 확장에서 공유 상태 정보 또는 리소스를 유지 관리하는 경우 드라이버 스레드(예: StartIo 루틴)는 물리적 디바이스 및 공유 데이터에 대한 액세스를 동일한 디바이스, 메모리 위치 또는 리소스에 액세스하는 드라이버의 다른 루틴과 동기화해야 합니다.
스레드가 ISR과 디바이스 또는 상태를 공유하는 경우 KeSynchronizeExecution 을 사용하여 드라이버 제공 SynchCritSection 루틴을 호출하여 디바이스를 프로그래밍하거나 공유 상태에 액세스해야 합니다. 중요 섹션 사용을 참조하세요.
스레드가 ISR 이외의 루틴과 상태 또는 리소스를 공유하는 경우 드라이버는 드라이버가 스토리지를 제공하는 드라이버 초기화된 임원 스핀 잠금으로 공유 상태 또는 리소스를 보호해야 합니다. 자세한 내용은 스핀 잠금을 참조하세요.
느린 디바이스에 드라이버 스레드를 사용하는 의 디자인 장단 부분에 대한 자세한 내용은 디바이스 폴링을 참조하세요. 하드웨어 우선 순위 관리도 참조하세요. 특정 지원 루틴에 대한 IRQL에 대한 자세한 내용은 루틴의 참조 페이지를 참조하세요.