다음을 통해 공유


상호 잠긴 큐 설정 및 사용

새 드라이버는 이 섹션에 설명된 메서드를 기본 설정하여 취소 안전 IRP 큐 프레임워크를 사용해야 합니다.

디바이스 전용 스레드가 있는 드라이버 또는 대부분의 시스템 FSD와 같은 임원 작업자 스레드를 사용하는 드라이버는 상호 잠긴 큐에서 자체 런타임 내부 IRP 큐를 관리할 가능성이 가장 높은 드라이버 유형입니다. WDM 드라이버를 포함한 모든 PnP 드라이버도 PnP 및 전원 상태 전환을 수행하는 동안 특정 IRP를 내부적으로 큐에 대기해야 합니다.

일반적으로 이러한 드라이버는 이중으로 연결된 상호 잠긴 큐를 설정합니다. 모든 IRP에는 드라이버가 현재 보유하고 있는 IRP를 이중으로 연결하는 데 사용할 수 있는 형식 LIST_ENTRY 멤버가 포함됩니다. 드라이버가 연결된 연동 큐를 설정하는 경우 재시도를 위해 IRP를 다시 큐에 추가할 수 없습니다.

드라이버는 디바이스 초기화 시 연결된 큐를 설정해야 합니다. 다음 그림에서는 이중으로 연결된 연동 큐, 드라이버가 이러한 큐를 설정하기 위해 호출해야 하는 지원 루틴 및 드라이버가 호출하여 IRP를 삽입하고 큐에서 IRP를 제거할 수 있는 ExInterlockedXxx 루틴 집합을 보여 줍니다.

상호 잠긴 큐를 사용하는 다이어그램

이 그림에서 알 수 있듯이 드라이버는 이중으로 연결된 인터락된 큐를 설정하기 위해 큐 자체 및 다음에 대한 스토리지를 제공해야 합니다.

  • 드라이버가 초기화하기 위해 KeInitializeSpinLock 을 호출해야 하는 임원 스핀 잠금입니다. 일반적으로 드라이버는 AddDevice 루틴에서 디바이스 개체에 대한 디바이스 확장을 설정할 때 스핀 잠금을 초기화합니다.

  • 드라이버가 InitializeListHead를 호출하여 초기화해야 하는 큐의 목록 헤드입니다.

이중으로 연결된 인터락된 큐를 사용하는 대부분의 드라이버는 드라이버에서 만든 디바이스 개체의 디바이스 확장에 필요한 스토리지를 제공합니다. 큐 및 임원 스핀 잠금은 컨트롤러 확장(드라이버가 컨트롤러 개체를 사용하는 경우) 또는 드라이버가 할당한 비페이지 풀에 있을 수 있습니다.

드라이버가 I/O 요청을 수락하는 동안 이전 그림과 같이 ListHeadLIST_ENTRY 형식인 경우 다음 지원 루틴 중 하나를 호출하여 IRP를 큐에 삽입할 수 있습니다.

큐 끝에 IRP를 배치하는 ExInterlockedInsertTailList

큐의 맨 앞에 IRP를 배치하는 ExInterlockedInsertHeadList입니다. 드라이버는 일반적으로 특정 요청을 다시 시도해야 하는 경우에만 이 루틴을 호출합니다.

드라이버는 IRP(ListEntry)에 대한 포인터와 이전에 초기화한 ListHead 및 이그제큐티브 스핀 잠금(잠금) 포인터를 이러한 각 ExInterlockedInsertXxxList 루틴에 전달해야 합니다. 드라이버가 ExInterlockedRemoveHeadList를 호출하여 IRP를 큐에서 제거하면 ListHeadLock에 대한 포인터만 필요합니다. 교착 상태를 방지하려면 드라이버가 ExInterlockedXxx 루틴에 전달하는 ExecutiveSpinLock을 보유해서는 안 됩니다.

인터록된 큐는 임원 스핀 잠금으로 보호되므로 드라이버는 이중으로 연결된 큐에 IRP를 삽입하고 IRQL = DISPATCH_LEVEL 이하에서 실행되는 드라이버 루틴에서 다중 프로세서로부터 안전한 방식으로 제거할 수 있습니다.

이전 그림과 같이 LIST_ENTRY 형식의 ListHead가 있는 큐는 이중으로 연결된 목록입니다. SLIST_HEADER 형식의 ListHead가 있는 목록은 시퀀싱된 링크된 목록입니다. 드라이버는 ExInitializeSListHead를 호출하여 시퀀싱된 연결 연동 큐에 대한 ListHead를 초기화합니다.

I/O 작업을 다시 시도하지 않는 드라이버는 ExInterlockedPushEntrySListExInterlockedPopEntrySList 를 사용하여 시퀀싱된 연결된 상호 잠긴 큐에서 내부적으로 IRP의 큐를 관리할 수 있습니다. 이 유형의 연동 큐를 사용하는 모든 드라이버는 이전 그림과 같이 SLIST_HEADER 형식의 ListHead 및 ExecutiveSpinLock에 상주 스토리지를 제공해야 합니다. 초기 항목을 큐에 삽입하려면 ExInterlockedPushEntrySList 를 호출하기 전에 스핀 잠금을 초기화하고 큐를 설정해야 합니다.

자세한 내용은 하드웨어 우선 순위스핀 잠금 관리를 참조하세요. 특정 지원 루틴에 대한 IRQL 요구 사항은 루틴의 참조 페이지를 참조하세요.