실행 중인 시스템에 PnP 디바이스 추가
이 섹션에서는 시스템이 사용자가 실행 중인 컴퓨터에 추가한 PnP 디바이스를 구성할 때 발생하는 일련의 이벤트에 대해 설명합니다. 이 설명에서는 새 디바이스를 열거하고 구성하는 PnP 관리자, 버스 드라이버 및 함수 및 필터 드라이버의 역할을 강조 표시합니다.
이 논의의 대부분은 컴퓨터가 부팅될 때 존재하는 PnP 디바이스를 구성하는 것과도 관련이 있습니다. 특히 드라이버가 INF 파일에 SERVICE_DEMAND_START 표시된 디바이스는 디바이스가 동적으로 추가되거나 부팅 시 존재하는지와 관계없이 기본적으로 동일한 방식으로 구성됩니다.
다음 그림에서는 사용자가 하드웨어를 컴퓨터에 연결하는 시점부터 디바이스를 구성하는 첫 번째 단계를 보여 줍니다.
플러그 앤 플레이 디바이스를 열거하고 보고하는 다이어그램
다음 주석은 이전 그림의 동그라미로 표시된 숫자에 해당합니다.
사용자가 PnP 디바이스를 PnP 버스의 무료 슬롯에 연결합니다.
이 예제에서 사용자는 PnP USB 조이스틱을 USB 호스트 컨트롤러의 허브에 연결합니다. USB 허브는 자식 디바이스를 연결할 수 있으므로 PnP 버스 디바이스입니다.
버스 디바이스의 함수 드라이버는 새 디바이스가 버스에 있는지 확인합니다.
드라이버에서 이를 결정하는 방법은 버스 아키텍처에 따라 달라집니다. 일부 버스에서는 기능 드라이버가 새 디바이스의 핫플러그 알림을 받습니다. 버스가 핫 플러그 알림을 지원하지 않는 경우 사용자는 제어판에서 적절한 조치를 취하여 버스가 열거되도록 해야 합니다.
이 예제에서 USB 버스는 핫 플러그 알림을 지원하므로 USB 버스의 함수 드라이버에 해당 자식이 변경되었다는 알림이 표시됩니다.
버스 디바이스의 함수 드라이버는 PnP 관리자에게 자식 디바이스 집합이 변경되었음을 알립니다.
함수 드라이버는 BusRelations형식을 사용해 IoInvalidateDeviceRelations을 호출하여 PnP 관리자에게 알립니다.
PnP 관리자는 버스의 드라이버에 버스의 현재 디바이스 목록을 쿼리합니다.
PnP 관리자는 버스에 대한 디바이스 스택에 IRP_MN_QUERY_DEVICE_RELATIONS 요청을 보냅니다. Parameters.QueryDeviceRelations.Type 값은 BusRelations, 이는 PnP 관리자가 버스(버스 관계)에 있는 디바이스의 현재 목록을 요청하고 있음을 나타냅니다.
PnP 관리자는 IRP를 버스에 대한 디바이스 스택의 최상위 드라이버로 보냅니다. PnP IRP에 대한 규칙에 따라 스택의 각 드라이버는 적절한 경우 IRP를 처리하고 IRP를 다음 드라이버로 전달합니다.
버스 디바이스의 함수 드라이버는 IRP를 처리합니다.
이 IRP 처리에 대한 자세한 내용은 IRP_MN_QUERY_DEVICE_RELATIONS의 참조 페이지를 확인하세요.
이 예제에서 USB 허브 드라이버는 허브 FDO대해 이 IRP를 처리합니다. 허브 드라이버는 조이스틱 장치에 대한 PDO를 만들며, IRP와 함께 반환되는 자식 장치 목록에 조이스틱 PDO에 대한 참조 포인터를 포함합니다.
USB 허브의 부모 버스 드라이버(USB 호스트 컨트롤러 클래스/미니클래스 드라이버 쌍)가 IRP를 완료하면, IRP는 허브 드라이버가 등록한 IoCompletion 루틴을 통해 디바이스 스택을 다시 거슬러 올라갑니다.
버스 기능 드라이버는 PnP 관리자가 자신의 자식 디바이스 목록을 쿼리하도록 요청하여 자식 목록의 변경을 보고합니다. 결과 IRP_MN_QUERY_DEVICE_RELATIONS 요청은 버스 디바이스에 대한 모든 드라이버에서 확인할 수 있습니다. 일반적으로 버스 함수 드라이버는 IRP를 처리하고 자식을 보고하는 유일한 드라이버입니다. 일부 디바이스 스택에서는 버스 필터 드라이버가 있으며 버스 관계 목록을 생성하는 데 참여합니다. 한 가지 예로 ACPI 디바이스용 버스 필터 드라이버로 연결하는 ACPI가 있습니다. 일부 디바이스 스택에서 비버스 필터 드라이버는 IRP_MN_QUERY_DEVICE_RELATIONS 요청을 처리하지만 일반적인 것은 아닙니다.
이 시점에서 PnP 관리자에는 버스의 현재 디바이스 목록이 있습니다. 그런 다음 PnP 관리자는 디바이스가 새로 도착했는지 또는 제거되었는지 확인합니다. 이 예제에는 하나의 새 디바이스가 있습니다. 다음 그림에서는 PnP 관리자가 새 디바이스에 대한 devnode를 만들고 디바이스 구성을 시작하는 방법을 보여줍니다.
다음 주석은 이전 그림의 동그라미로 표시된 숫자에 해당합니다.
PnP 매니저는 버스에서 새 자식 디바이스에 대한 디브노드를 만듭니다.
PnP 관리자는 IRP_MN_QUERY_DEVICE_RELATIONS IRP에서 반환된 버스 관계 목록을 PnP 디바이스 트리에 현재 기록된 버스의 자식 목록과 비교합니다. PnP 관리자는 각 새 디바이스에 대한 devnode를 만들고 제거된 모든 디바이스에 대한 제거 처리를 시작합니다.
이 예제에는 하나의 새 디바이스(조이스틱)가 있으므로 PnP 관리자는 조이스틱에 대한 devnode를 만듭니다. 이 시점에서 조이스틱에 대해 구성된 유일한 드라이버는 조이스틱의 PDO를 만든 부모 USB 허브 버스 드라이버입니다. 선택적 버스 필터 드라이버도 디바이스 스택에 있지만 이 예제에서는 단순성을 위해 버스 필터 드라이버를 생략합니다.
이전 그림에서 USB 허브 devnode와 조이스틱 devnode 사이에 있는 넓은 화살표는 조이스틱 devnode가 USB 허브 devnode의 자식임을 나타냅니다.
PnP 관리자는 새 디바이스에 대한 정보를 수집하고 디바이스 구성을 시작합니다.
PnP 관리자는 디바이스 스택에 일련의 IRP를 전송하여 디바이스에 대한 정보를 수집합니다. 이 시점에서 디바이스 스택은 디바이스의 부모 버스 드라이버가 만든 PDO와 선택적 버스 필터 드라이버에 관한 필터 DO로만 구성됩니다. 따라서 버스 드라이버와 버스 필터 드라이버는 이러한 IRP에 응답하는 유일한 드라이버입니다. 이 예제에서 조이스틱 디바이스 스택의 유일한 드라이버는 부모 버스 드라이버인 USB 허브 드라이버입니다.
PnP 관리자는 디바이스 스택에 IRP를 전송하여 새 디바이스에 대한 정보를 수집합니다. 이러한 IRP에는 다음이 포함됩니다.
IRP_MN_QUERY_ID다음과 같은 하드웨어 ID 유형 각각에 대한 별도의 IRP입니다.
- BusQueryDeviceID
- BusQueryInstanceID
- BusQueryHardwareIDs
- BusQueryCompatibleIDs
- BusQueryContainerID
IRP_MN_QUERY_DEVICE_TEXT다음 각 항목에 대한 별도의 IRP입니다.
- DeviceTextDescription
- 장치텍스트위치정보
PnP 관리자는 새 PnP 디바이스를 처리하는 이 단계에서 위에 나열된 IRP를 보내지만 반드시 나열된 순서로는 안 되므로 IRP가 전송되는 순서를 가정해서는 안 됩니다. 또한 PnP 관리자가 위에 나열된 IRP만 전송한다고 가정해서는 안 됩니다.
PnP 관리자는 레지스트리를 확인하여 디바이스가 이전에 이 컴퓨터에 설치되었는지 여부를 확인합니다. PnP 관리자는 < 분기 아래 있는 디바이스에 대해 ><\> 하위 키를 확인합니다. 이 예제에서 디바이스는 새 디바이스이며 "처음부터" 구성해야 합니다.
PnP 관리자는 레지스트리에 디바이스에 대한 정보를 저장합니다.
레지스트리의 열거형 섹션은 시스템 구성 요소에서 사용하도록 할당되어 있으며 구조는 변경될 수 있습니다. 드라이버 작성자는 시스템 루틴을 사용하여 드라이버와 관련된 정보를 추출해야 합니다. 드라이버에서 직접 열거형 분기에 액세스하지 마세요. 다음 열거형 정보는 디버깅 목적으로만 나열됩니다.
PnP 관리자는 디바이스 열거자의 키 아래에 디바이스에 대한 하위 키를 만듭니다.
PnP 관리자는 HKLM\System\CurrentControlSet\Enum\<열거자>\<deviceID>라는 하위 키를 만듭니다. 아직 없는 경우 <열거자> 하위 키를 만듭니다.
열거자는 PnP 하드웨어 표준을 기반으로 PnP 장치를 검색하는 구성 요소입니다. 열거자의 작업은 PnP 관리자와 협력하여 PnP 버스 드라이버에 의해 수행됩니다. 디바이스는 일반적으로 PCI 또는 PCMCIA와 같은 부모 버스 드라이버에 의해 열거됩니다. 일부 디바이스는 ACPI와 같은 버스 필터 드라이버에 의해 열거됩니다.
PnP 관리자는 이 디바이스 인스턴스에 대한 하위 키를 만듭니다.
Capabilities.UniqueID이 IRP_MN_QUERY_CAPABILITIES에 대해 TRUE로 반환되는 경우, 디바이스의 고유 ID는 시스템 전체에서 고유합니다. 그렇지 않은 경우 PnP 관리자는 ID를 시스템 전체에서 고유하게 수정합니다.
PnP 관리자는 이라는 하위 키를 HKLM\System\CurrentControlSet\Enum\<열거자>\<deviceID>\<instanceID>경로에 만듭니다.
PnP 관리자는 디바이스 인스턴스의 하위 키에 디바이스에 대한 정보를 씁니다.
PnP 관리자는 디바이스에 대해 제공된 경우 다음을 비롯한 정보를 저장합니다.
- deviceDesc
- IRP_MN_QUERY_DEVICE_TEXT - 위치 - 에서 IRP_MN_QUERY_DEVICE_TEXT
- 기능 - IRP_MN_QUERY_CAPABILITIES 플래그
- UINumber - IRP_MN_QUERY_CAPABILITIES
- 하드웨어 ID - IRP_MN_QUERY_ID
- CompatibleIDs - IRP_MN_QUERY_ID
- ContainerID - IRP_MN_QUERY_ID
- LogConf\BootConfig - IRP_MN_QUERY_RESOURCES
- LogConf\BasicConfigVector - IRP_MN_QUERY_RESOURCE_REQUIREMENTS
- deviceDesc
이 시점에서 PnP 관리자는 함수 드라이버를 찾고 디바이스에 대한 드라이버를 필터링할 준비가 된 것입니다(있는 경우). (다음 그림을 참조하세요.)
함수 및 필터 드라이버를 찾는 방법을 보여 주는
다음 노트는 이전 그림의 번호가 매겨진 원에 해당합니다.
커널 모드 PnP 관리자는 사용자 모드 PnP 관리자 및 사용자 모드 설치 구성 요소와 조정하여 디바이스에 대한 함수 및 필터 드라이버를 찾습니다(있는 경우).
커널 모드 PnP 관리자는 설치가 필요한 디바이스를 식별하고, 이를 사용자 모드 PnP 관리자에게 알리기 위해 큐에 이벤트를 넣습니다. 권한 있는 사용자가 로그인하면 사용자 모드 구성 요소는 드라이버 찾기를 진행합니다. 설치 구성 요소 및 디바이스 설치에 대한 해당 역할에 대한 자세한 내용은 디바이스 및 드라이버 설치참조하세요.
사용자 모드 설치 구성 요소는 커널 모드 PnP 관리자에게 함수를 로드하고 드라이버를 필터링하도록 지시합니다.
사용자 모드 구성 요소는 커널 모드로 다시 호출하여 드라이버를 로드시키고, 그 결과 AddDevice 루틴이 호출됩니다.
다음 그림에서는 PnP 관리자가 드라이버를 로드하고(해당하는 경우), AddDevice 루틴을 호출하고, 드라이버에 디바이스를 시작하도록 지시하는 방법을 보여 줍니다.
adddevice 루틴을 호출하고 새 디바이스를 시작하는 방법을 보여 주는
다음 노트는 이전 그림의 번호가 매겨진 원에 해당합니다.
하위 필터 드라이버
함수 드라이버가 디바이스 스택에 연결되기 전에 PnP 관리자는 하위 필터 드라이버를 처리합니다. 각 하위 필터 드라이버에 대해 PnP 관리자는 드라이버가 아직 로드되지 않은 경우 드라이버의 DriverEntry 루틴을 호출합니다. 그런 다음 PnP 관리자는 드라이버의 AddDevice 루틴을 호출합니다. AddDevice 루틴에서 필터 드라이버는 필터 디바이스 개체(필터 DO)를 만들고 디바이스 스택(IoAttachDeviceToDeviceStack)에 연결합니다. 디바이스 개체를 디바이스 스택에 연결하면 드라이버는 디바이스의 드라이버로 작동합니다.
USB 조이스틱 예제에는 디바이스에 대한 하위 필터 드라이버가 하나 있습니다.
함수 드라이버
하위 필터가 부착된 후, PnP 관리자는 함수 드라이버를 처리합니다. PnP 관리자는 드라이버가 아직 로드되지 않은 경우 함수 드라이버의 DriverEntry 루틴을 호출하고 함수 드라이버의 AddDevice 루틴을 호출합니다. 함수 드라이버는 FDO(함수 디바이스 개체)를 만들어 디바이스 스택에 연결합니다.
이 예제에서 USB 조이스틱의 함수 드라이버는 실제로 HID 클래스 드라이버와 HID 미니클래스 드라이버와 같은 한 쌍의 드라이버입니다. 두 드라이버는 함께 작동하여 함수 드라이버 역할을 합니다. 드라이버 쌍은 FDO를 하나만 만들고 디바이스 스택에 연결합니다.
상위 필터 드라이버
함수 드라이버가 연결되면 PnP 관리자는 모든 상위 필터 드라이버를 처리합니다.
이 예제에는 디바이스에 대한 상위 필터 드라이버가 하나 있습니다.
리소스 할당 및 디바이스 시작
PnP 관리자는 필요한 경우 디바이스에 리소스를 할당하고 IRP를 발급하여 디바이스를 시작합니다.
리소스 할당
구성 프로세스의 앞부분에서 PnP 관리자는 디바이스의 부모 버스 드라이버에서 디바이스에 대한 하드웨어 리소스 요구 사항을 수집했습니다. 디바이스에 대한 드라이버의 전체 집합이 로드되면 PnP 관리자는 디바이스 스택에 IRP_MN_FILTER_RESOURCE_REQUIREMENTS 요청을 보냅니다. 스택의 모든 드라이버는 이 IRP를 처리하고 필요한 경우 디바이스의 리소스 요구 사항 목록을 수정할 수 있습니다.
PnP 관리자는 디바이스 요구 사항 및 현재 사용 가능한 리소스에 따라 디바이스에 리소스가 필요한 경우 디바이스에 리소스를 할당합니다.
PnP 관리자는 새 디바이스의 요구 사항을 충족하기 위해 기존 디바이스의 리소스 할당을 다시 정렬해야 할 수 있습니다. 이 리소스 재할당을 "재조정"이라고 합니다. 기존 디바이스에 대한 드라이버는 리밸런스 중에 일련의 중지 및 시작 IRP를 수신하지만 사용자에게는 리밸런스가 투명해야 합니다.
USB 조이스틱 예제에서 USB 디바이스에는 하드웨어 리소스가 필요하지 않으므로 PnP 관리자는 리소스 목록을 NULL설정합니다.
디바이스 시작(IRP_MN_START_DEVICE)
PnP 관리자가 디바이스에 리소스를 할당하면 디바이스 스택에 IRP_MN_START_DEVICE IRP를 전송하여 드라이버가 디바이스를 시작하도록 지시합니다.
디바이스가 시작된 후 PnP 관리자는 디바이스의 드라이버에 세 개의 IRP를 더 보냅니다.
-
스타트 IRP가 성공적으로 완료되면 PnP 관리자는 또 다른 IRP_MN_QUERY_CAPABILITIES IRP를 디바이스 스택으로 보냅니다. 디바이스의 모든 드라이버에는 IRP를 처리하는 옵션이 있습니다. 기능 또는 필터 드라이버가 기능 정보를 수집하기 위해 디바이스에 액세스해야 할 수 있으므로 PnP 관리자는 모든 드라이버가 연결되고 디바이스가 시작된 후 이 IRP를 보냅니다.
-
예를 들어 이 IRP는 디바이스 관리자 및 핫플러그 프로그램과 같은 사용자 인터페이스에 디바이스를 표시해서는 안 된다고 보고할 수 있는 기회를 드라이버에 제공합니다. 이 기능은 시스템에 있지만 현재 구성에서 사용할 수 없는 디바이스(예: 랩톱의 게임 포트)에 유용하며 랩톱이 도킹 해제될 때 사용할 수 없습니다.
버스 관계에 대한 IRP_MN_QUERY_DEVICE_RELATIONS
PnP 관리자는 이 IRP를 전송하여 디바이스에 자식 디바이스가 있는지 여부를 확인합니다. 이 경우 PnP 관리자는 각 자식 디바이스를 구성합니다.
GUID_PNP_LOCATION_INTERFACE 사용
GUID_PNP_LOCATION_INTERFACE 인터페이스는 디바이스에 SPDRP_LOCATION_PATHS PnP(플러그 앤 플레이) 디바이스 속성을 제공합니다.
드라이버에서 이 인터페이스를 구현하기 위해서는 InterfaceType이 GUID_PNP_LOCATION_INTERFACE인 상태로 IRP_MN_QUERY_INTERFACE IRP를 처리하십시오. 드라이버는 인터페이스의 개별 루틴에 대한 포인터를 포함하는 PNP_LOCATION_INTERFACE 구조체에 대한 포인터를 제공합니다. PnpGetLocationString 루틴 디바이스의 SPDRP_LOCATION_PATHS 속성의 디바이스별 부분을 제공합니다.