서비스 제어 처리기 함수

각 서비스에는 서비스 프로세스가 서비스 제어 프로그램에서 제어 요청을 받을 때 컨트롤 디스패처에서 호출하는 제어 처리기 처리기 함수가 있습니다. 따라서 이 함수는 컨트롤 디스패처의 컨텍스트에서 실행됩니다. 예제는 컨트롤 처리기 함수 작성을 참조하세요.

서비스는 RegisterServiceCtrlHandler 또는 RegisterServiceCtrlHandlerEx 함수를 호출하여 해당 서비스 제어 처리기 함수를 등록합니다.

서비스 제어 처리기가 호출될 때 서비스는 SetServiceStatus 함수를 호출하여 제어 코드를 처리하면 서비스 상태 변경되는 경우에만 해당 상태 SCM에 보고해야 합니다. 제어 코드를 처리해도 서비스 상태 변경되지 않는 경우 SetServiceStatus를 호출할 필요가 없습니다.

서비스 제어 프로그램은 ControlService 함수를 사용하여 제어 요청을 보낼 수 있습니다. 모든 서비스는 SERVICE_CONTROL_INTERROGATE 제어 코드를 수락하고 처리해야 합니다. SetServiceStatus를 호출하여 다른 컨트롤 코드의 동의를 사용하거나 사용하지 않도록 설정할 수 있습니다. SERVICE_CONTROL_DEVICEEVENT 제어 코드를 받으려면 RegisterDeviceNotification 함수를 호출해야 합니다. 서비스는 추가 사용자 정의 제어 코드를 처리할 수도 있습니다.

서비스에서 SERVICE_CONTROL_STOP 제어 코드를 수락하는 경우 수신 시 중지하여 SERVICE_STOP_PENDING 또는 SERVICE_STOPPED 상태로 설정해야 합니다. SCM이 이 제어 코드를 보낸 후에는 다른 제어 코드를 보내지 않습니다.

Windows XP: 서비스가 NO_ERROR 반환하고 계속 실행되면 제어 코드를 계속 받습니다. 이 동작은 Windows Server 2003 및 Windows XP SP2(서비스 팩 2)부터 변경되었습니다.

컨트롤 처리기는 30초 이내에 반환해야 합니다. 그렇지 않으면 SCM에서 오류를 반환합니다. 서비스에서 제어 처리기를 실행할 때 서비스가 긴 처리를 수행해야 하는 경우 긴 처리를 수행하는 보조 스레드를 만든 다음 컨트롤 처리기에서 반환해야 합니다. 이렇게 하면 서비스가 컨트롤 디스패처를 묶지 않습니다. 예를 들어 시간이 오래 걸리는 서비스에 대한 중지 요청을 처리할 때 중지 프로세스를 처리할 다른 스레드를 만듭니다. 컨트롤 처리기는 SERVICE_STOP_PENDING 메시지를 사용하여 SetServiceStatus를 호출하고 를 반환해야 합니다.

사용자가 시스템을 종료하면 SERVICE_ACCEPT_PRESHUTDOWN 제어 코드를 사용하여 SetServiceStatus를 호출한 모든 컨트롤 처리기가 SERVICE_CONTROL_PRESHUTDOWN 제어 코드를 받습니다. 서비스 제어 관리자는 서비스가 중지되거나 지정된 preshutdown 제한 시간 값이 만료될 때까지 기다립니다(이 값은 ChangeServiceConfig2 함수를 사용하여 설정할 수 있습니다). 이 알림을 처리하는 서비스는 서비스가 중지되거나 사전 종료 시간 제한 간격이 만료될 때까지 시스템 종료를 차단하기 때문에 이 제어 코드는 특별한 상황에서만 사용해야 합니다.

preshutdown 알림이 완료된 후 SERVICE_ACCEPT_SHUTDOWN 제어 코드를 사용하여 SetServiceStatus를 호출한 모든 컨트롤 처리기는 SERVICE_CONTROL_SHUTDOWN 제어 코드를 받습니다. 설치된 서비스의 데이터베이스에 표시되는 순서대로 알림을 받습니다. 기본적으로 서비스는 시스템이 종료되기 전에 정리 작업을 수행하는 데 약 20초가 걸립니다. 이 시간이 만료되면 서비스 종료가 완료되었는지 여부에 관계없이 시스템 종료가 진행됩니다. 시스템이 종료 상태로 남아 있는 경우(다시 시작되거나 전원이 끄지 않음) 서비스가 계속 실행됩니다.

서비스를 정리하는 데 더 많은 시간이 필요한 경우 대기 힌트와 함께 STOP_PENDING 상태 메시지를 전송하므로 서비스 컨트롤러는 서비스 종료가 완료된 시스템에 보고하기 전에 대기하는 시간을 알 수 있습니다. 그러나 서비스가 종료를 중지하지 않도록 하기 위해 서비스 컨트롤러가 대기하는 기간에 제한이 있습니다. 서비스가 서비스 스냅인을 통해 종료되는 경우 제한은 125초 또는 125,000밀리초입니다. 운영 체제가 다시 부팅되는 경우 시간 제한은 다음 레지스트리 키의 WaitToKillServiceTimeout 값(밀리초)에 지정됩니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

중요

서비스는 이 값을 수정하여 시간 제한을 늘리려고 시도해서는 안 됩니다. WaitToKillServiceTimeout을 직접 설정해야 하는 경우 값은 밀리초 단위여야 합니다.

고객은 운영 체제를 빠르게 종료해야 합니다. 예를 들어 UPS 전원에서 실행되는 컴퓨터가 UPS 전원이 부족하기 전에 종료를 완료할 수 없는 경우 데이터가 손실될 수 있습니다. 따라서 서비스는 정리 작업을 가능한 한 빨리 완료해야 합니다. 데이터를 정기적으로 저장하고, 디스크에 저장된 데이터를 추적하고, 종료 시 저장되지 않은 데이터만 저장하여 저장되지 않은 데이터를 최소화하는 것이 좋습니다. 컴퓨터가 종료되고 있으므로 할당된 메모리 또는 기타 시스템 리소스를 해제하는 데 시간을 소비하지 마세요. 종료 중임을 서버에 알려야 하는 경우 네트워크 문제로 인해 서비스 종료가 지연 될 수 있으므로 회신을 기다리는 데 소요된 시간을 최소화합니다.

서비스 종료 중에 기본적으로 SCM은 종속성을 고려하지 않습니다. SCM은 실행 중인 서비스 목록을 열거하고 SERVICE_CONTROL_SHUTDOWN 명령을 보냅니다. 따라서 의존하는 다른 서비스가 이미 중지되었으므로 서비스가 실패할 수 있습니다.

서비스의 종료 순서를 수동으로 설정하려면 서비스 이름을 종료해야 하는 순서대로 포함된 다중 문자열 레지스트리 값을 만들고 다음과 같이 제어 키의 PreshutdownOrder 값에 할당합니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order"

애플리케이션에서 종속 서비스의 종료 순서를 설정하려면 SetProcessShutdownParameters 함수를 사용합니다. SCM은 이 함수를 사용하여 처리기 0x1E0 우선 순위를 지정합니다. SCM은 컨트롤 처리기가 호출되면 SERVICE_CONTROL_SHUTDOWN 알림을 보내고, 해당 제어 처리기에서 돌아오기 전에 서비스가 종료되기를 기다립니다.

컨트롤 처리기 함수 작성