본문 바로가기

High Level Technique/Window System

커널 오브젝트 상태 (Kernel Object State)

커널 오브젝트 상태 (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