Chapter 7) 프로세스 간 통신(IPC) 1 - Signaled vs Non-Signaled
아는개발자
2023. 4. 20. 14:29
■ 커널 오브젝트의 상태
Non-Signaled 상태(FALSE) → Signaled 상태(TRUE)
신호를 받지 않은 상태 → 신호를 받은 상태
◇ 프로세스 커널 오브젝트의 상태에 대한 이해
커널 오브젝트의 상태가 변하는 시점은 커널 오브젝트의 종류에 따라서 달라진다.
처음 커널 오브젝트 생성 시점에는 Non-Signaled,
프로세스가 종료되면 Signaled 상태.
하지만 종료된 프로세스는 다시 실행을 재개하지 못한다.
즉, Signaled → Non-Signaled 상태로 변경되지 못한다.
◇ 커널 오브젝트의 두 가지 상태를 확인하는 용도의 함수
/// <summary>
/// hHandle이 가리키는 커널 오브젝트가 Signaled 상태가 되었을 때 반환
/// </summary>
DWORD WaitForSingleObject(
HANDLE hHandle, // 1
DWORD dwMilliseconds // 2
);
1. hHandle
상태 확인을 원하는 커널 오브젝트의 핸들
2. dwMilliseconds
커널 오브젝트가 Signaled 상태가 될 때까지 기다릴 수 있는 최대 시간
DWORD WaitForMultipleObjects(
DWORD nCount, // 1
const HANDLE* lpHandles, // 2
BOOL bWaitAll, // 3
DWORD dwMilliseconds // 4
);
// If the function failes, the return value is WAIT_FAILED.
1. nCount
배열에 저장되어있는 핸들 개수
2. lpHandles
핸들을 저장하고 있는 배열의 주소 정보
3. bWaitAll
관찰 대상이 모두 Signaled 상태가 되기를 기다리고자 하는지(TRUE)
하나라도 Signaled 상태가 되면 반환할 것인지 (FALSE)
4. dwMilliseconds
커널 오브젝트가 Signaled 상태가 될 때까지 기다릴 수 있는 최대 시간
◇ 커널 오브젝트의 상태 확인이 필요한 상황의 연출
두 개의 자식 프로세스를 생성해서 각각 1부터 5까지, 그리고 6부터 10까지 덧셈을 시킨 다음 그 결과를 반환하게 하자.
그리고 부모 프로세스는 반환된 값을 더해서 그 결과를 출력하는 형태로 작성하자.
/*
* PartAdder.cpp
*
* 프로그램 설명: 전달된 인자 사이의 수 덧셈
*/
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR* argv[])
{
if (argc != 3)
return -1;
DWORD start = _ttoi(argv[1]);
DWORD end = _ttoi(argv[2]);
DWORD total = 0;
for (DWORD i = start; i <= end; i++) {
total += i;
}
return total;
}
책에서는 518이 나왔으며, STILL_ACTIVE가 259가 나와 그런 것이라 추측한다. 그렇다면 윈도우 64bit 환경에서는 137이 의미하는 바가 STILL_ACTIVE인가?
Microsoft에서 제공하는 문서를 확인했을 때 win32환경이나 win64환경을 별도로 구분하지는 않는 것으로 보이고, STILL_ACTIVE는 259가 맞다.
여기서 나는 한가지 가설을 세워보았다. 하나는 정상적으로 프로세스가 종료되었고, 다른 하나는 프로세스가 종료되기 이전에 부모 프로세스의 코드가 실행되었다면 어떨까?
274-259 = 15 첫 번째 프로세스의 계산을 하면 1부터 5까지 더하는 것이고, 이 결과는 15이다.
즉, 첫 번째 자식 프로세스는 정상적으로 계산을 마치고 15가 반환되었으나 두 번째 자식 프로세스가 여전히 실행되고 있을 때 부모 프로세스 쪽에서 GetExitCodeProcess() 처리를 하면서 이런 결과가 나온 것을 예측할 수 있다.