* 해당 글은 윤성우의 뇌를 자극하는 윈도우즈 시스템 프로그래밍 도서를 읽고 정리한 글입니다
https://product.kyobobook.co.kr/detail/S000001223395
* 우리가 사용하는 Windows는
멀티 프로세스(Multi-Process) 운영체제, 프로세스라는 것이 여러개 존재할 수 있는 운영체제이다
* 프로세스
실행 중인 프로그램
* 실행파일(.exe, Executable File)
단순히 데이터만 담고 있는 파일과 달리,
컴퓨터가 읽고 실행할 수 있는 명령어가 담긴 파일로, 컴퓨터에게 특정 작업을 지시하고 실행하도록 만드는 파일
ㄴ 실행과정
운영체제의 프로그램 로더가 실행파일을 읽고 메모리에 적재
CPU는 메모리에 적재된 명령어를 읽고 실행하여 프로그램을 동작시킴
ㄴ 특징
① CPU가 이해할 수 있는 기계어로 구성
실행파일은 컴파일된 이진 코드로 작성된다
② 운영체제와의 종속성
실행파일은 특정 운영체제에서만 동작한다
- Windows: .exe
- Linux/Unix: ELF 파일
- macOS: Mach-O 파일
③ 실행 가능한 코드와 데이터 포함
명령어(코드), 데이터(변수, 상수), 리소스(아이콘, 문자열 등) 포함
* 프로세스를 구성하는 요소
: Code 영역, Data영역, Heap 영역, Stack 영역
① 코드(Code) 영역
프로세스가 실행할 코드와 매크로 상수가 기계어 형태로 저장된 공간
CPU는 코드 영역에 저장된 명령어를 하나씩 가져와서 실행
컴파일 타임에 결정되고, 중간에 코드를 바꿀 수 없어 Read-Only로 지정
→ 이 영역을 세분화하면 code와 rodata로 나눠짐
1) code - 오직 읽기 전용
우리가 작성한 코드가 컴파일된 후 기계어로 번역되어 저장되어 있는 곳
EIP 레지스터를 통해 읽어서 코드가 실행됨
프로그램이 끝날 때까지 메모리에 남아 있음
2) rodata - 오직 읽기 전용
읽기 전용인 데이터가 들어 있음
ㄴ 주로 상수, 상수형 문자열, printf의 중괄호 부분이 들어감
② 데이터(Data) 영역
코드에서 선언한 전역변수와 정적변수가(static)가 저장되는 영역
ㄴ 전역변수(단, 다른 파일에서 접근하려면 extern 선언 필요) - 프로그램 전체에서 공유
ㄴ static 변수 - 특정 함수에서 값을 유지
ㄴ 전역 static 변수 - 특정 파일 내에서만 사용 가능한 값을 유지
프로그램 시작과 함께 할당되며, 프로그램이 종료되면 소멸
실행 도중에 값이 변경될 수 없게 Read-Write로 지정
→ 이 영역을 세분화하면 BSS와 Data로 나눠짐
1) BSS
초기화 값이 없는 값
2) data
초기화 값이 있는 값
③ 스택(Stack) 영역
함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역
함수의 호출과 함께 할당되며, 함수의 호출이 완료되며 소멸
이렇게 스택 영역에 저장되는 함수의 호출 정보를 스택 프레임(Stack Frame)이라고 함
④힙(Heap)영역
사용자가 직접 메모리 관리하는 곳
사용자에 의해 메모리 공간이 동적으로 할당되고 해제
* Register Set
CPU 내에 존재하는 레지스터들은 현재 실행 중인 프로그램을 위한 데이터로 채워진다
따라서, 레지스터들의 상태까지도 프로세스의 일부로 포함시켜 말할 수 있다
* 프로세스의 스케줄링(Scheduling)
하나의 CPU가 여러 개의 프로세스를 번갈아 가면서 실행하는데
이 때, 프로세스의 CPU 할당 순서 및 방법을 결정짓는 일을 가리켜 스케줄링이라고 한다
* 프로세스의 상태 변화
프로세스가 생성되어 소멸되기까지 겪는 상태의 변화
상태의 종류 : Start, Ready, Running, Blocked, end
- Start → Ready
프로세스 생성과 동시에 Ready 상태로 들어간다
Reay 상태에 있는 프로세스는 CPU에 의해 실행되기를 희망한다
- Ready → Running
Ready 상태에 있는 프로세스 중 스케줄러에 의해 선택된 프로세스는 Running 상태가 되어 실행됨
- Running → Ready
우선 순위 낮아짐, 자원을 사용할 시간이 초과됨, 운영체제의 스케줄링 정책에 의해
현재 사용 중인 자원을 반납하고 다시 Ready 상태로 전환
- Running → Blocked
데이터 입출력에 관련된 일을 하는 경우 실행 중인 프로세스가 실행을 멈추는 상태로 전환
- Blocked → Ready
입출력 작업이 완료된 프로세스는 다시 CPU를 사용하기 위해 Ready 상태로 전환
* 컨텍스트 스위칭(Context Switching)
자원을 반납하는 프로세스 A 관련 레지스터 정보는 메모리에 저장되고,
자원을 획득하는 프로세스 B 관련 레지스터 정보는 CPU의 레지스터에 복원시킨다
* 실행되는 프로세스의 변경과정에서 발생하는 컨텍스트 스위칭은 시스템에 많은 부담을 준다
* 프로세스의 생성
CreateProcess 함수를 호출하는 프로세스를 가리켜 부모 프로세스(Parent Process),
CreateProcess 함수 호출에 의해 생성된 프로세스를 가리켜 자식 프로세스(Child Process)라 한다
BOOL CreateProcessA(
[in, optional] LPCSTR lpApplicationName,
[in, out, optional] LPSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCSTR lpCurrentDirectory,
[in] LPSTARTUPINFOA lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
lpApplicationName
: 생성할 프로세스의 실행파일 이름을 인자로 전달
lpCommandLine
: 실행할 명령어줄
(예) main 함수에 인자 전달
lpProcessAttributes
: 프로세스의 보안 속성을 지정할 때 사용하는 인자
lpThreadAttributes
: 스레드의 보안 속성을 지정할 때 사용하는 인자
bInheritHandles
: 전달인자가 TRUE인 경우,
생성되는 자식 프로세스는 부모 프로세스가 소유하는 핸들 중 상속 가능한 핸들을 상속한다
전달인자가 FALSE인 경우, 핸들이 상속되지 않는다
dwCreationFlags
: 생성하는 프로세스의 특성을 결정지을 때 사용되는 옵션
특별히 설정할 필요가 없을 경우 0을 전달
lpEnvironment
: 프로세스마다 Environment Block(환경 블록)이라는 메모리 블록을 관리한다
이 블록을 통해서 프로세스가 실행에 필요로 하는 문자열을 저장할 수 있다
lpCurrentDirectory
: 생성하는 프로세스의 현재 디렉터리를 설정하는 인자
lpStartupInfo
: STARTUPINFO 또는 STARTUPINFOEX 구조체 변수를 초기화한 다음에 이 변수의 인자를 포인터를 인자로 전달
lpProcessInformation
: 생성하는 프로세스 정보를 얻기 위해 사용되는 인자
PROCESS_INFORMATION 구조체 변수의 주소값을 인자로 전달
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR* argv[])
{
DWORD val1, val2;
val1 = _ttoi(argv[1]);
val2 = _ttoi(argv[2]);
_tprintf(_T("%d + %d = %d\n"), val1, val2, val1 + val2);
_gettchar();
return 0;
}
1. STARTUPINFO 구조체 변수의 생성 및 초기화
2. 현재 디렉터리의 설정
3. CreateProcess 함수의 호출
첫 번째. 전달인자를 통해서 실행파일 이름을 전달할 경우,
현재 디렉터리 기준으로 실행파일을 찾는다
두 번째. 전달인자를 통해서 실행파일 이름을 전달한 경우,
표준 검색 경로 순서대로 실행파일을 찾는다
[표준 검색 경로 순서]
- 실행 중인 프로세스의 실행파일이 존재하는 디렉터리
- 실행 중인 프로세스의 현재 디렉터리
- Windows의 시스템 디렉터리
- 환경변수 PATH에 의해 지정되어 있는 디렉터리
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <stdlib.h>
#define DIR_LEN MAX_PATH + 1
int _tmain(int argc, TCHAR* argv[])
{
STARTUPINFO si = { 0, };
PROCESS_INFORMATION pi;
si.dwFillAttribute = STARTF_USEPOSITION | STARTF_USESIZE;
si.dwX = 100;
si.dwY = 200;
si.dwXSize = 300;
si.dwYSize = 200;
LPCWSTR title = _T("I am a boy!");
si.lpTitle = new TCHAR[_tcslen(title) + 1];
_tcscpy_s(si.lpTitle, _tcslen(title) + 1, title);
TCHAR command[] = _T("AdderProcess.exe 10 20");
TCHAR cDir[DIR_LEN];
BOOL state;
GetCurrentDirectory(DIR_LEN, cDir); // 현재 디렉터리 확인
_fputts(cDir, stdout);
_fputts(_T("\n"), stdout);
SetCurrentDirectory(_T("exe")); // 상대 경로로 설정함
// AdderProcess.exe는 만든 exe 폴더 안에 있음
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);
if (state != 0)
_fputts(_T("Creation OK!\n"), stdout);
else
_fputts(_T("Creation Error!\n"), stdout);
return 0;
}
'IT공부 > IT서적' 카테고리의 다른 글
[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 7장. 프로세스간 통신(IPC) - 1 (0) | 2025.01.07 |
---|---|
[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 6장. 커널 오브젝트와 오브젝트 핸들 (0) | 2024.12.31 |
[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 4장. 컴퓨터 구조 - 2 (0) | 2024.12.24 |
[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 3장. 64비트 기반 프로그래밍 (0) | 2024.12.21 |
[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 2장. 아스키코드 vs 유니코드 (0) | 2024.12.21 |