프로세스 생성
사전 준비사항
// 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함수의 리턴값이 설정 된다.
- Kernel Object Table내에 있으며 해당 프로세스가 살아있을 경우
#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 이상 일때
- Process