디바이스와 상호 작용하는 Win32 서비스
디바이스와 상호 작용하는 INF AddService 를 통해 설치된 이상적인 Win32 서비스는 드라이버 가 디바이스와 상호 작용하는 방식과 유사하게 작동합니다. 디바이스의 존재에 따라 드라이버가 로드되고 언로드되며, 디바이스와 상호 작용하는 Win32 서비스는 디바이스의 존재에 따라 이와 동일한 시작 및 중지 패턴을 따라야 합니다.
서비스는 디바이스 인터페이스가 있고 디바이스 인터페이스가 더 이상 사용하도록 설정되지 않은 경우 상호 작용하고 중지할 수 있는 경우에만 시작해야 합니다. 이 디자인 패턴은 원치 않는 동작과 정의되지 않은 동작을 최소화하는 강력한 서비스를 보장합니다. 이 패턴을 따르도록 서비스를 설계하는 방법을 살펴보겠습니다.
서비스 설치
서비스를 설치하려면 INF AddService 지시문을 사용합니다. 이렇게 하면 서비스를 만들고 시작할 수 있습니다.
서비스 수요 시작을 만드는 설정을 추가합니다. 이 작업은 서비스 트리거를 시작하게 하는 StartType=0x3 설정하여 수행할 수 있습니다.
이 섹션의 마지막 단계는 AddTrigger 지시문을 사용하여 디바이스 인터페이스가 도착할 때 서비스를 시작하도록 하는 것입니다(AddTrigger에 대한 자세한 내용은 AddService 참조). 다음은 AddTrigger를 사용하는 방법의 예입니다.
[UserSvc_Install]
ServiceType = 0x10 ; SERVICE_WIN32_OWN_PROCESS
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 0 ; SERVICE_ERROR_IGNORE
ServiceBinary = %13%\oemsvc.exe
AddTrigger = UserSvc_AddTrigger
[UserSvc_AddTrigger]
TriggerType = 1 ; SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL
Action = 1 ; SERVICE_TRIGGER_ACTION_SERVICE_START
SubType = %GUID_DEVINTERFACE_OSRFX2% ; Interface class GUID
DataItem = 2, "USB\VID_0547&PID_1002" ; SERVICE_TRIGGER_DATA_TYPE_STRING
DataItem에 지정된 HardwareId는 선택 사항이며 일반적으로 일반 클래스 인터페이스를 사용하여 트리거를 보다 구체적인 디바이스에 scope 경우에만 필요합니다.
서비스 런타임
런타임 관점에서 서비스의 첫 번째 단계는 디바이스 인터페이스 알림을 등록하는 것입니다. 이 작업을 수행하는 방법에 대한 규범적인 지침은 디바이스 인터페이스 도착 및 디바이스 제거 알림 등록 페이지에서 찾을 수 있습니다.
특히 CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE 플래그와 함께 CM_Register_Notification 사용하여 디바이스 인터페이스 알림의 적절한 등록을 수행해야 합니다.
참고
서비스를 시작할 때 도착 알림이 이미 전달되었을 수 있으므로 디바이스 인터페이스 알림을 받게 될 것이라는 사실에 의존할 수 없습니다. 특히 디바이스 인터페이스 도착이 서비스 시작의 원인인 경우입니다. 대신 이미 인터페이스가 있는 경우 검사 디바이스 인터페이스 목록을 가져와야 합니다.
디바이스 인터페이스에 대한 알림을 등록하면 새 디바이스 인터페이스를 사용하도록 설정하거나 기존 디바이스 인터페이스를 사용하지 않도록 설정하는 것에 대한 알림이 표시됩니다. 알림 콜백에서 디바이스 인터페이스 경로를 검색할 수 있습니다. 기존 디바이스 인터페이스 목록을 쿼리하여 서비스가 시작되고 알림을 등록하기 전에 존재하는 디바이스 인터페이스를 검사하려면 CM_Get_Device_Interface_List 같은 API를 통해 디바이스 인터페이스 목록을 가져올 수 있습니다.
참고
알림을 등록하고 시스템에 이미 있는 디바이스 인터페이스 목록을 검색하는 사이에 디바이스 인터페이스가 도착할 가능성이 있습니다. 이 경우 디바이스 인터페이스는 알림 콜백과 디바이스 인터페이스 목록 모두에 나열됩니다.
I/O API를 사용하여 디바이스 인터페이스와 상호 작용하려는 경우 원하는 디바이스 인터페이스를 찾은 후 CreateFile을 통해 인터페이스에 대한 핸들을 엽니다.
다음 단계는 보조 처리당 알림을 등록하여 디바이스 제거 시도 또는 디바이스 제거 시도와 같은 디바이스의 상태 변경에 대한 알림을 받는 것입니다. 이 작업은 CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE 플래그와 함께 CM_Register_Notification 사용하여 수행할 수 있습니다. 디바이스 인터페이스 도착 및 디바이스 제거 알림 등록의 지침에 따라 디바이스가 사라지면 핸들을 적절하게 해제할 수 있습니다.
서비스가 상호 작용할 수 있는 마지막 디바이스 인터페이스의 제거가 서비스를 중지할 수 있도록 디바이스 인터페이스 도착 및 제거를 추적해야 합니다. 마지막 인터페이스가 제거되면 서비스를 중지합니다(자세한 내용은 이 페이지에서 찾을 수 있습니다). 이 작업은 다음 단계를 수행하여 수행할 수 있습니다.
SCM에 SERVICE_STOP_PENDING 상태를 게시하여 서비스가 중단됨을 나타냅니다.
서비스에서 사용하던 모든 항목을 초기화/클린
SERVICE_STOP 상태를 SCM에 게시하여 중지 작업을 완료합니다.
서비스가 중지되는 경우 에 대해 검사 기존 열려 있는 모든 핸들을 디바이스 인터페이스(없을 수 있음)로 이동하여 클린 합니다.
디바이스 인터페이스는 디바이스 설치 중, 디바이스 사용/사용 안 함, 디바이스 다시 열거, 시스템 다시 부팅 중 또는 나열되지 않은 다른 시나리오 중에 돌아올 수 있습니다. 디바이스 인터페이스가 다시 돌아오면 트리거 시작 등록에 따라 서비스가 트리거됩니다.
이 흐름은 서비스가 디바이스 인터페이스의 도착 시 시작되고 마지막 디바이스 인터페이스가 더 이상 없을 때 중지되도록 합니다.
코드 샘플 & 관련 링크
GitHub에는 서비스가 이러한 이벤트 흐름을 활용하는 방법을 안내하는 샘플이 있습니다. 샘플은 Win32 서비스 샘플에서 찾을 수 있습니다.
또한 AddService 페이지에서 AddTrigger에 대한 유용한 설명서를 찾을 수 있습니다.