커널 오브젝트 상태 (Kernel Object State)
Windows 운영체제에 의해 생성되는 커널 오브젝트는 두가지 상태가 존재한다.
Signaled, Non-Signaled 이 두가지 인데, 이러한 값은 커널 오브젝트를 구성하는 멤버변수에 FASLE, TRUE를 이용하여 상태를 저장한다.
처음 커널 오브젝트가 생성되면 Non-Signaled 상태가 된다. 그러다 프로세스가 종료되면 Signaled 상태가 된다. 즉, 실행 중일 때는 Non-Signaled가 되고 종료 시에는 Signaled 상태가 되는 것이다.
이를 보고 프로세스가 실행 중인지 종료된 것인지 알 수 있는 것이다.
그렇다면 Non-Signaled에서 Signaled 상태로 가는 것은 당연하게 생각할 수 있다. 실행하다 종료가 되는 것이니까. 그럼 반대로 Signaled에서 Non-Signaled로 가는 상태도 존재할까? 풀어 쓰자면 종료된 프로세스가 다시 실행되는 것이다. 이러한 상황은 불가능하고 Non-Signaled 상태가 되기 위해서는 다시 프로세스를 실행해야 한다. (새로운 프로세스가 실행되는 것이다.)
WaitForSingleObject()
WaitForSingleObject()는 커널 오브젝트의 상태를 확인하기 위한 함수이다. 함수명 그대로 오브젝트의 상태가 Signaled가 될 때까지 기다리는 것이다.
WatiForSingleObject()의 파라미터는 핸들값과 시간인데 여기서 핸들은 해당 프로세스의 핸들이며 시간은 Signaled가 될 때까지 기다릴 수 있는 최대의 시간을 말한다.
그렇다면 부모 프로세스에서 자식 프로세스1과 2를 생성하여 자식 프로세스 1에서는 1~5까지 더하고 자식 프로세스 2에서는 6~10까지 더하여 부모 프로세스에서 각 값을 더하여 출력하는 프로그램을 작성해 보자.
PartAdder.cpp
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int main(int argc, char* argv[])
{
if (argc != 3)
{
return -1;
}
DWORD start = atoi(argv[1]);
DWORD end = atoi(argv[2]);
int total = 0;
for (int i = start; i <= end; i++)
{
total += i;
}
return total;
}
NonStopAdderManager.cpp
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
int main(void)
{
STARTUPINFO si1 = { 0, };
STARTUPINFO si2 = { 0, };
PROCESS_INFORMATION pi1;
PROCESS_INFORMATION pi2;
DWORD return_val1;
DWORD return_val2;
TCHAR command1[] = _T("PartAdder.exe 1, 5");
TCHAR command2[] = _T("PartAdder.exe 6, 10");
DWORD sum = 0;
si1.cb = sizeof(si1);
si2.cb = sizeof(si2);
CreateProcess(NULL, command1, NULL, NULL, TRUE, 0, NULL, NULL, &si1, &pi1);
CreateProcess(NULL, command2, NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2);
CloseHandle(pi1.hThread);
CloseHandle(pi2.hThread);
GetExitCodeProcess(pi1.hProcess, &return_val1);
GetExitCodeProcess(pi2.hProcess, &return_val2);
if (return_val1 == -1 || return_val2 == -1)
{
return -1;
}
sum += return_val1;
sum += return_val2;
printf("total: %d\n", sum);
CloseHandle(pi1.hProcess);
CloseHandle(pi2.hProcess);
return 0;
}
출력 결과는 아래와 같다.
결국 1부터 10까지 더하는 프로그램이지만 결과 값이 518로 전혀 다른 결과가 나타났다.
위와 같은 결과가 나온 이유는 다음과 같다.
GetExitCodeProcess()에 의해서 return 값이 나오고 난 뒤에 해당 프로세스가 종료되어야 하는 것이 맞다. 하지만 자식 프로세스가 생성되고 모든 연산을 마치고 종료되는 것은 무리가 있다.
그래서 WaitForSingleObject()를 사용하는 것이다.
GetExitCodeProcess()가 실행되기 전에 WaitForSingleObject()를 이용하여 Signaled 상태가 된 것을 확인 한 후에 GetExitCodeProcess 를 이용하여 반환된 값을 가져오는 것이다.
이렇게 정상적으로 출력이 된다.
'High Level Technique > Window System' 카테고리의 다른 글
Pseudo Handle, Handle Duplicate (0) | 2016.12.28 |
---|---|
핸들 테이블과 오브젝트 핸들의 상속 (0) | 2016.12.28 |
메일 슬롯 (Mail Slot) (0) | 2016.12.27 |
커널 오브젝트 (Kernel Object) (0) | 2016.12.26 |
프로세스 (0) | 2016.12.26 |