5장 프로세스 생성과 소멸 (2) - 미완성

Lamjwi·2024년 1월 3일

Section 04 : 프로세스의 생성

  • 스케줄링 알고리즘과 프로세스의 우선순위에 대해서 언급
  • Windows 시스템의 프로그래밍 알려면 쓰레드, 커널 오브젝트 및 핸들에 대한 지식이 필요

프로세스의 생성

  • 기본적인 프로세스 생성법
    • 실행파일 더블클릭
  • 시스템 프로그래머라면 다른 방법
    • "프로그램 실행 중에 또 하나의 프로세스 생성"
    • MS워드에서 실행중 갑자기 익스폴로저 실행하는 등등
    • 사칙연산 가능한 계산기 만들고 이외의 것을 요구하면 Windows 보조프로그램 있는 계산기 띄우는것 만들 것이다.

CreateProcess 함수의 이해

  • Windows는 프로세스 생성을 돕기 위해서 CreateProcess 함수를 제공한다
    • 부모 프로세스(Parent Process)
      • CreateProcess 함수를 호출하는 프로세스
    • 자식 프로세스(Child Process)
      • CreateProcess 함수 호출에 의해서 생성된 프로세스
    • 생성하는 생성되는 프로세스 간에는 부모 자식 간의 관게가 형성
  • p144 5-13 사진
	BOOL CreateProcess (
    p144 코드 사진
  1. ipApplicationName
    • 생성할 프로세스의 실행파일 이름을 인자로 전달한다.
    • 경로명을 추가로 지정 할 수 있고 지정하지 않는다면 프로그램의 현재 디렉터리(Current Directory)에서 실행파일을 찾게 된다.
  2. ipCommandLine
    • main함수에 인자를 전달해본적 잇을것
    • argc, argv라는 이름으로 문자열의 개수와 문자열들이 전달되는데, 이처럼 새로 생성하는 프로세스에 인자를 전달할 떄 매개변수를 사용한다.
    • 1번에 Null을 전달하고, 두번쨰 전달인자에 실행파일의 이름을 더불어 전달도 가능하다
      • 실행파일의 이름은 표준 검색 경로를 기준으로 찾는다.
  3. lpProcessAttributes
    • 프로세스의 보안 속성을 지정할 때 사용하는 인자로서 보통은 NULL을 전달하고, 이러한 경우 디폴트(기본적인) 보안 속성이 지정된다.
  4. lpThreadAttributes
    • 새로 생성되는 스레드의 보안 속성을 지정합니다. 대부분 NULL을 사용하여 기본 보안 속성을 사용합니다.
  5. bInheritHandle
    • 상속 가능한 핸들을 자식 프로세스가 상속받을 수 있게 할지의 여부를 지정합니다. 일반적으로 TRUE를 설정하여 핸들 상속을 허용합니다.
  6. dwCreationFlags
    • 새로 생성되는 프로세스의 우선순위 및 생성 옵션을 지정합니다. 특별히 설정할 필요가 없을 경우에는 0을 전달한다.
  7. lpEnvironment
    • 새로 생성되는 프로세스에 전달될 환경 변수 블록을 지정합니다. NULL을 지정하면 부모 프로세스의 환경 블록을 상속받습니다.
  8. lpCurrentDirectory
    • 새로 생성되는 프로세스의 현재 디렉터리를 지정합니다. NULL을 지정하면 부모 프로세스의 현재 디렉터리를 상속받습니다.
  9. lpStartupInfo
    • STARTUPINFO구조체 변수를 초기화한 다음에 이 변수의 포인터를 인자로 전달한다.
    • STARTUPINFO 구조체 변수는 생성하는 프로세스의 속성을 지정할떄 사용된다.
  10. lpProcessInformation
    • 생성된 프로세스의 정보를 받기 위해 사용되는 인자다. PROCESS_INFORMATION 구조체에 변수의 주소값을 인자로 전달한다.
    • 전달된 주소값이 가리키는 변수에 프로세스 정보가 채워진다.
  • ㅅㅂ.

예제를 통한 CreateProcess 함수의 이해.

/*
   AdderProcess.cpp
   프로그램 설명: main 함수의 전달인자를 합산하는 프로그램
*/

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

int _tmain(int argc, TCHAR* argv[])
{
    DWORD val1, val2;
    val1=_ttoi(argv[1]);				// 1
    val2=_ttoi(argv[2]);				// 2

    _tprintf(_T("%d + %d = %d \n"), val1, val2, val1+val2);

    _gettchar(); // 3 프로그램의 실행을 잠시 멈추기 위해
    return 0;
}
  • main함수를 통해서 전돨되는 두 개의 인자를 정수형 데이터로 변경한 다음 덧셈 결과를 출력하는 프로그램이다.
  • 1~2행
    • ttoi 함수는 문자열 데이터를 정수형 데이터로 변경시키는 atoi 함수와 유니코드 기반의 _wtoi를 동시 지원하기 위한 매크로다.
  • 3행
    • getchar 함수와 유니코드 기반의 getwchar 함수 동시지원하는 매크로다.
#ifdef 	_UNICODE
#define _ttoi    _wtoi
#define _gettchar getwchar
#else
#define _ttoi    atoi
#define _gettchar getchar
#endif
  • 나중가면 이런거 생략함 MSDN을 참조하는 습관을 길러라.
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#define DIR_LEN MAX_PATH+1

int _tmain(int argc, TCHAR* argv[])
{
	STARTUPINFO si = { 0, };			// 1
	PROCESS_INFORMATION pi;
	
    // 2
	si.cb = sizeof(si);					// 3
	si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;	// 4
	si.dwX = 100;	// 5
	si.dwY = 200;	// 6
	si.dwXSize = 300;
	si.dwYSize = 200;
	si.lpTitle = _T("I am a boy!");	// 7

	TCHAR command[] = _T("AdderProcess.exe 10 20");
	TCHAR cDir[DIR_LEN];
	BOOL state;

	GetCurrentDirectory(DIR_LEN, cDir); // 9 현재 디렉토리 확인	
	_fputts(cDir, stdout);				// 10
	_fputts(_T("\n"), stdout);

	SetCurrentDirectory(_T("C:\\WinSystem")); // 11 디렉토리 변경

	GetCurrentDirectory(DIR_LEN, cDir); // 변경된 디렉토리 확인
	_fputts(cDir, stdout);
	_fputts(_T("\n"), stdout);

	state = CreateProcess( // 프로세스 생성
		NULL,               // 실행파일의 이름
		command,            // main 함수에 전달될 문자열
		NULL, NULL, TRUE,
		CREATE_NEW_CONSOLE,
		NULL, NULL, &si, &pi		// 8
	); //CreateProcess

	if (state != 0)
	{
		_fputts(_T("Creation OK! \n"), stdout);
	}
	else
	{
		_fputts(_T("Creation Error! \n"), stdout);
	}

	return 0;
}
  • 위에서 제시한 프로그램을 실행시기 위한 프로그램이다. 이 예제 실행시 이게 부모 전전게 자식.

프로세스 생성 1단계 : STARTUPINFO 구조체 변수의 생성 및 초기화

  • 1번은 STARTUPINFO 구조체 변수를 선언과 동시에 0으로 초기화함, 이 변수는 CreateProcess 함수의 9번쨰 인자로 들어가는 요소로서, 생성하는 프로세스의 속성을 지정하는 용도로 사용된다.
  • 2번들은 생성하고자 하는 프로세스의 속성을 지정하고 있다.
typedef struct _STARTUPINFO {
    DWORD cb;             // 구조체 크기의 크기
    LPTSTR lpReserved;   
    LPTSTR lpDesktop;     
    LPTSTR lpTitle;       // 콘솔 윈도우 타이틀 바 제목
    DWORD dwX;            // 프로세스 윈도우의 X 좌표
    DWORD dwY;            // 프로세스 윈도우의 Y 좌표
    DWORD dwXSize;        // 프로세스 윈도우의 가로 길이
    DWORD dwYSize;        // 프로세스 윈도우의 세로 길이
    DWORD dwXCountChars;
    DWORD dwYCountChars;  
    DWORD dwFillAttribute; 
    DWORD dwFlags;        // 설정된 멤버의 정보
    WORD  wShowWindow;    
    WORD  cbReserved2;   
    LPBYTE lpReserved2;   
    HANDLE hStdInput;     
    HANDLE hStdOutput;    
    HANDLE hStdError;     
} STARTUPINFO, *LPSTARTUPINFO;
  • // 쪽만 보면 된다.
  • 3번은 구조체 변수 si의 바이트 단위 크기로 맴버변수 cb를 초기화한다.확장성을 고려한 맴버다.
  • 4번은 si 구조체 변수에 설정되어 있는 값들 중에서 반영코자 하는 멤버들에 대한 정보를 설정하고 있다.
    • STARTF_USEPOSITION은 구조체 맴버 중에서 dwY와 dwX의 값을 참조해서, 생성하는 프로세스 원도우 위치를 결정할때 사용된다. 아무리 dwX와 dwY가 값을 지니고 있다 하더라도, dwFlags에 STARTF_USEPOSITION가 설정되지 않으면 아무런 의미가 없다. ㅅㅂ.
  • 5번 6번은 생성하는 프로세스 콘솔의 위치를 설정해 준다. 5,6번 밑에 줄들은 생성하는 프로세스 콘솔 원도우 크기를 설정해 주고 있다.(값들 변경하면서 실행해보기)
  • 7번은 지정한 문자열은 프로세스 원도우의 타이틀 바 제목을 지정할 때 사용된다.
  • 8번은 이렇게 초기화된 구조체 변수 si는 8번에서 인자로 전달되고 있다.

프로세스 생성 2단계 : 현재 디렉터리의 설정

  • 현재 디렉터리(Current Directory)
    • 파일의 생성 및 개방하는 함수의 호출 과정에서 디렉터리 경로를 포함하는 완전경로(Full Path)를 사용하지 않고, 파일 이름만을 전달해 본 경험이 있을것이다.
    • 특정 파일을 찾을 경우에 기본이 되는 디렉터리다.
    • 일반적으로 프로세스가 생성되면 프로세스의 현재 디렉터리는 프로세스의 실행파일이 존재하는 디렉터리로 설정된다.
DWORD GetCurrentDirectory(
    DWORD  nBufferLength,
    LPTSTR lpBuffer
);
	If the function fails, the return value is zero.
  • 실행 중에 있는 프로세스의 현재 디렉터리 위치보여주는 함수
  • 두번쨰 전달인자 lpBuffer
    • 현재 디렉터리 정보가 저장될 메모리 버퍼의 포인터다.
  • 첫번째 전달인자 nBufferLength
    • 현재 디렉터리 정보가 저장될 메모리 버퍼의 크기로서, 바이트 단위 길이 정보가 아니라, 저장 가능한 문자열 길이 정보가 전달되어야 한다.
  • MAX_PATH는
    • Windows에서 사용하는 일련경로(Full Path)의 최대 길이가 얼마인지를 알려준다.
    • windef.h에 선언되어있다.
BOOL SetCurrentDirectory (
    LPCTSTR lpPathName
);

	If the function fails, the return value is zero.
  • 프로세스의 현재 디렉터리는 변경도 가능하다
    • 호출 시 유의할 점
      • lpPathName은 변경하고자 하는 현재 디렉터리 경로를 저장하며 한다.
  • 9,10번은 현재 디렉터리 정보를 추출해서 출력하고 있다. 이 출력결과를 통해서 기본적으로 구성되는 현재 디렉터리가 어디인지 확인할 수 있다.
  • 11번은 현재 디렉터리를 C드라이브 아래에 있는 WinSystem이라는 디렉터리로 변경학고 있다. 예제 실행을 위해서 C드라이브에 WinSystem이라는 디렉터리 만들어 두기 바란다.

프로세스 생성 3단계 : CreateProcess 함수의 호출

Section 05 : 프로세스 생성과 관련된 예제 그리고 문제점

Section 06 : 명령 프롬프트 프로젝트 기능추가

1차 24.01.03
2차 24.01.04
3차 24.01.05
4차 24.01.09
5차 24.01.10

profile
ㅇㅅㅇ

0개의 댓글