HOWTO: 비동기 프로시저 호출을 이용하여 Waitable 타이머 사용 하기

HOWTO: 비동기 프로시저 호출을 이용하여 Waitable 타이머 사용 하기

기술 자료 ID : 601487
마지막 검토 : 2003년 6월 27일 금요일
수정 : 2.0
이 문서는 이전에 다음 ID로 출판되었음: KR601487

요약

Waitable 타이머는 임의의 시간 또는 정기적으로 신호를 알리는 커널 개체입니다. 비동기 프로시저 호출 (APC) 는 타이머가 신호를 보낼 때 마다 콜백 함수가 실행되도록 Waitable 타이머와 연동될 수 있습니다. 본 문서의 샘플 코드는 이것을 어떻게 구현하는지 보여 주고 있습니다.

위로 가기

추가 정보

Waitable 타이머들을 사용할 때 상수 WIN32_WINNT 를 0x0400으로 정의할 필요가 있습니다. 이 상수는 적절한 Waitable 타이머 함수 원형이 선언되는지 확인하기 위한 <windows.h> 의 포함 이전에 정의되어야 합니다.

CreateWaitableTimer() 을 호출함으로써 Waitable 타이머을 생성할 수 있습니다. 이 함수는 커널 개체에 핸들을 반환합니다. 타이머가 이미 존재하고 있다면 OpenWaitableTimer() 을 사용함으로써 프로세스 관련 핸들을 구할 수 있습니다. CreateWaitableTimer() 또는 OpenWaitableTimer() 중 어떤 것을 통해서 구해지든 간에 그 핸들은 타이머가 더 이상 필요하지 않게 되었을 때 릴리즈 되어야 합니다. CloseHandle() 을 호출하여 이것을 실행합니다.

타이머는 SetWaitableTimer() 호출로써 설정됩니다. 타이머는 특정한 시간으로 설정될 수 있습니다 (예: December 16, 1999 at 9:45 PM) 또는 상대 시간(예: 지금부터 5 분). SetWaitableTimer() 는 Due Time 을 위한 LARGE_INTEGER 를 필요로 합니다. 이 값은 FILETIME 구조에 의해서 설명된 포맷 내에 존재하고 있어야 합니다. 만일 이 값이 양의 값을 갖는다면 그것은 특정한 시간을 의미하며 음의 값을 갖는다면 100-nanosecond 단위 내에서의 Relative Time을 의미하는 것입니다. 나중에 보시게 될 샘플 코드는 Relative Time 을 사용하고 있습니다. 타이머는 SetWaitableTimer() 호출 이후 5초 동안 신호를 보내게 될 것 입니다.

타이머를 정기적으로 자체적인 신호를 보낼 수 있도록 설정할 수 있습니다. 세 번째 매개 변수로써 정기적인 값(milliseconds 단위)을 SetWaitableTimer()에 넘겨줌으로써 진행합니다. 정기적인 타이머가 필요하다면 CreateWaitableTimer()에 두 번째 매개 변수로써 FALSE 를 넘겨 줌으로써 타이머를 자동으로 설정되는 타이머로 만들어야 합니다. 이 샘플은 2 초 간격으로 타이머를 설정합니다.

타이머가 설정되었을 때 Waitable 타이머와 비동기 프로시저 호출 (APC) 함수를 연동할 수 있습니다. APC 함수는 Completion 루틴(Routine)이라고 합니다. Completion 루틴(Routine)의 주소는 SetWaitableTimer()의 네번째 매개 변수입니다. 다섯 번째 매개변수는 인자(Arguments)를 Completion 루틴(Routine)으로 넘겨 주기 위해서 사용하는 Void Pointer 입니다.

모든 APC들에 있기 때문에 스레드는 Completion Routine 를 실행하기 위해서 Alertable State 에 있어야만 합니다. Completion 루틴(Routine)은 SetWaitableTimer() 라고 하는 동일한 스레드에 의해서 실행될 것입니다. 그래서 이 스레드는 결국에는 그 자체가 Alertable State 로 되어야만 합니다. 다음의 Alertable 함수들 중에 하나를 호출함으로써 이것을 진행할 수 있습니다:

각각의 스레드는 APC 큐를 가지고 있습니다. 함수들 중에 하나가 호출되었을 때 스레드의 APC 큐내에 엔트리가 있다면 그 스레드는 Sleep으로 들어가지 않습니다. 대신에 해당 엔트리는 APC 큐에서 제거되며 Completion 루틴(Routine)이 호출됩니다.

어떠한 엔트리도 APC 큐 내에 존재하지 않는 경우 스레드는 Wait 가 충족될 때까지 정지됩니다. Wait 는 APC 큐에 엔트리를 추가함, Timeout, 핸들 신호, 또는 MsgWaitForMultipleObjectsEx()의 경우에는 스레드의 메시지 큐에 메시지를 추가함으로써 충족될 수 있습니다. APC 큐에 있는 엔트리에 의해서 Wait 가 충족되면 스레드는 활성화되고 Completion 루틴(Routine)은 호출됩니다. 이러한 경우에 해당 함수의 반환되는 값은 WAIT_IO_COMPLETION 입니다.

중요: Completion 루틴(Routine)이 실행되고 난 후 시스템은 처리하기 위해서 APC 큐 내에 있는 또 다른 엔트리를 점검합니다. Alertable 함수는 모든 APC 엔트리들이 처리되고 나서야 반환될 것입니다 그러므로 엔트리들이 처리될 수 있는 것 보다 빠른 APC 큐에 엔트리들이 추가되고 있다면 이들 함수들 중 하나의 함수 호출은 절대로 반환되지 않는 것이 가능합니다. 이것은 특별하게 Completion 루틴(Routine)을 실행하는데 필요한 시간보다 그 주기가 짧은 Waitable 타이머들에서 가능합니다.

APC 와 함께 Waitable 타이머를 사용하는 중일 때 스레드는 타이머를 타이머의 핸들상에서 대기하지 않도록 설정합니다. 이것을 사용함으로써, APC 큐에 엔트리가 추가되는 것에 대한 결과가 아닌 타이머가 신호를 내보내는 것에 대한 결과로 인하여 스레드를 활성화하게 됩니다. 결과적으로 스레드는 더 이상 알림 상태(Alertable State)에 있지 않게 되며 Completion 루틴(Routine)은 호출되지 않습니다. 다음의 샘플에서 SleepEx() 는 스레드를 Alertable State 에 넣기 위해서 사용됩니다. 타이머가 신호 처리되고 난 후 스레드의 APC 큐에 엔트리를 추가하였을 때 SleepEx() 은 해당 스레드를 활성화 시킵니다.

샘플 코드

위로 가기

참조

추가 정보를 보시려면 Microsoft Knowledge Base에 있는 다음 문서를 참고하시기 바랍니다.

188768 (http://support.microsoft.com/kb/188768/KO/) INFO: Working with the FILETIME Structure

“Advanced Windows”, Third Edition, Jeffrey Richter’s, Chapter 15, “Alertable I/O,” Microsoft Press, 1997

위로 가기

Author: yyjksw