(Win32 : WindowsProgramming-16) Process Creation, ExitCode, Inherit KO

Posted by : at

Category : win32   WindowsProgramming


프로세스 생성

사전 준비사항

// sample.cpp
// C:\\Windows\\Sample.exe 에 넣는다
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

int _tmain(int argc, TCHAR* argv[])
{
    for(int i = 0; i < argc; i++)
    {
        _tprintf(_T("argv[%d] : %s\n"), i, argv[i]);
    }

    TCHAR name[256] = { 0 };
    GetCurrentDirectory(256, name);
    _tprintf(_T("current directory : %s\n"), name);

    _tprintf(_T("press enter key to quit\n"), name);
    getchar();

    return 100;
}

프로세스 생성

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

int _tmain()
{
    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO si = { 0 };
    si.cb = sizeof(si);

    TCHAR name[] = _T("C:\\Windows\\Sample.exe");
    TCHAR args[] = _T("Sample.exe A B C D");

    BOOL b = CreateProcess(name, args, 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, 0, &si, &pi);

    if(b)
    {
        // Process, Thread Kernel Object가 생성되기에 Close해 주어야 한다.
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        // Close를 반드시 해줘야 하는 것이 Kernel Object의 참조개수가 올라가 있기에
        // Close를 해주지 않으면 생성된 프로세스가 종료되지 않음.
    }

    return 0;
}

CreateProcessA에 대한 설명

BOOL CreateProcessA(
  LPCSTR                lpApplicationName,      // 프로그램의 이름, 만약 0이라면 현재 디렉터리 or PATH에서 exe검색함.
  LPSTR                 lpCommandLine,          // args(반드시 버퍼에 담아서 보내야함.)
  LPSECURITY_ATTRIBUTES lpProcessAttributes,    // 생성되는 프로세스의 Process Kernel Object의 보안속성 설정
  LPSECURITY_ATTRIBUTES lpThreadAttributes,     // 생성되는 프로세스의 Thread Kernel Object의 보안속성 설정
  BOOL                  bInheritHandles,        // Object Handle Table을 상속할 것인가
  DWORD                 dwCreationFlags,        // 프로세스 우선순위, 생성 플래그 (CREATE_NEW_CONSOLE : 생성되는 프로세스도 새로운 콘솔을 쓰겠다.)
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,     // 생성되는 프로세스의 시작 디렉터리를 지정
  LPSTARTUPINFOA        lpStartupInfo,          // 생성되는 프로세스 생성시 옵션지정
  LPPROCESS_INFORMATION lpProcessInformation    // 자녀 프로세스 정보
);

프로세스 종료 코드

  • 종료 코드
    • Kernel Object Table내에 있으며 해당 프로세스가 살아있을 경우 STILL_ACTIVE가 담겨있다.
    • 프로세스가 종료 되면 main함수의 리턴값이 설정 된다.
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

int _tmain()
{
    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO si = { 0 };
    si.cb = sizeof(si);

    TCHAR name[] = _T("C:\\Windows\\Sample.exe");
    TCHAR args[] = _T("Sample.exe A B C D");

    BOOL b = CreateProcess(name, args, 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, 0, &si, &pi);

    if(b)
    {
        // CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    // pi.hProcess를 통해서 자식 프로세스에 접근 가능
    // 종료 코드 꺼내보기
    while(1)
    {
        int cmd;
        scanf_s("%d", &cmd);

        if(cmd == 1)
        {
            DWROD code;
            // 프로세스가 종료될 경우 PKO내에 종료코드가 들어간다
            // GetExitCodeProcess는 PKO내의 종료코드를 확인하는 함수이다
            GetExitCodeProcess(pi.hProcess, &code);

            if(code == STILL_ACTIVE)
                _tprintf(_T("child alive\n"));
            else
                _tprintf(_T("exit code %d\n"), code);
        }
    }
    return 0;
}

강제로 죽이기

while(1)
{
    int cmd;
    scanf_s("%d", &cmd);

    if(cmd == 2)
    {
        TerminateProcess(pi.hProcess, 300); // 300이 종료 코드가 된다.

        // 참고로 TerminateProcess는 비동기 함수이다.
        // 종료를 요청만 해두고 종료는 이후에 일어난다.
        // 아래에서 바로 자식 프로세스가 종료되지 않는 현상이 발생할 수 있음.

        // 진짜로 종료되었는지 조사해보기
        // -> 핸들이 시그널 되었는지 조사
        WaitForSingleObject(pi.hProcess, INFINITE);
    }

    if(cmd == 1)
    {
        DWROD code;
        GetExitCodeProcess(pi.hProcess, &code);

        if(code == STILL_ACTIVE)
            _tprintf(_T("child alive\n"));
        else
            _tprintf(_T("exit code %d\n"), code);
    }
}
  • Kernel Object에 따라 signal 조건이 다르다.
    • Process
      • Signal : 죽을 때
      • Non Signal : 살아 있는 동안
    • Thread
      • Signal : 죽을 때
      • Non Signal : 살아 있는 동안
    • FILE
      • Signal : R/W 작업이 종료
      • Non Signal : R/W 작업 중
    • MUTEX
      • Signal : 소유자가 없을 때
      • Non Signal : 소유자가 있을 때
    • SEMAPHORE
      • Signal : 카운트가 0
      • Non Signal : 카운트가 0 이상 일때

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links