책정리/윈도우 API 정복2

40장 프로세스

GONII 2019. 4. 4. 23:21

01 프로세스

. 프로세스와 스레드

프로세스(Process)

실행 중인 프로그램, 실행파일이 실행되어 메모리에 적재된 상태
실행중인 프로그램의 인스턴스
운영체제는 실행된 프로그램을 프로세스 단위로 관리함
프로세스는 각각 4GB 주소 공간과 파일, 메모리, 스레드 등의 객체들을 소유하며 프로세스가 종료될 프로세스가 소유한 모든 자원은 운영체제에 의해 파괴됨
모든 것은 프로세스에 의해 소유되며 스레드는 윈도우와 메시지 , 스택만 소유함
객체간의 소유 관계는 프로세스 > 스레드 > 윈도우 정리 있다
프로세스는 실행중인 프로그램이지만 실제로 작업하는 주체는 스레드(Thread) 담당함
프로세스는 메모리상에 존재하기만 뿐이며 실행과 동시에 스레드를 하나 만들고 스레드를 호출함으로써 스레드에게 모든 작업을 맡긴다.
정리하자면 프로세스는 스레드를 담는 껍데기이며 실제 일을 하는 것은 스레드이다.
프로세스는 최소한 이상의 스레드를 가진다.
프로세스와 동시에 만들어지는 스레드를 스레드(Primary Thread) 하며 이외에 필요에 따라 여러 개의 스레드를 만들어 사용할 있다.

. 프로세스의 생성

프로그램에서 다른 프로그램을 실행하고자 때는 Win32 API 제공하는 프로세스 생성 함수를 사용함

UINT WinExec( LPCSTR lpCmdLine, UINT uCmdShow ) ;

LpCmdLine 인수로 실행하고자 하는 프로그램의 이름을 전달하되 완전 경로를 수도 있다.
실행 파일명만 주어졌을 때는 다음 순서대로 실행 파일의 위치를 검색하여 실행함
프로그램이 실행된 디렉토리 -> 현재 디렉토리 -> 시스템 디렉토리 -> 윈도우즈 디렉토리 -> PATH 환경변수가 지정하는 디렉토리들
WinExec 프로세스를 성공적으로 생성했을 경우 31보다 값을 리턴함

에러값 설명
0 메모리나 리소스가 부족하여 프로세스를 생성하지 못하였다
ERROR_BAD_FORMAT 지정한 파일이 실행 파일이 아니다
ERROR_FILE_NOT_FOUND 파일이 없다
ERROR_PATH_NOT_FOUND 경로가 없다.

프로세스를 생성하면 주소 공간을 할당하고 스레드를 생성하고 관련 DLL 모두 읽어오고 초기화 작업까지 완료해야 프로세스가 생성됨.
WinExec 생성된 프로세스가 처음으로 GetMessage함수를 호출할 리턴함
프로세스가 일련의 초기화 작업을 마무리하고 스스로 메시지를 처리할 있을 비로소 리턴함
DWORD LoadModule( LPCSTR lpModuleName, LPVOID lpParameterBlock) ;

DWORD LoadModule( LPCSTR lpModuleName, LPVOID lpParameterBlock) ;

인수로 구조체의 포인터를 넘겨야 하는데 특별히 필요하지도 않은 옵션임에도 구조체를 완전히 완성해야 하고, 구조체는 헤더 파일에 선언조차 되어 있지 않아 직접 구조체를 선언한 사용해야
16비트 함수인데다 별다른 이점이 없어 거의 사용되지 않음

. CreateProcess

Win32 API에서 프로세스를 생성하는 기본 함수는 CreateProcess이다
BOOL CreateProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL blnheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) ;

BOOL CreateProcess(
	LPCTSTR lpApplicationName,
    LPTSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL blnheritHandles, DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCTSTR lpCurrentDirectory,
    LPSTARTUPINFO lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation);

lpApplicationName
실행하고자 하는 프로그램의 이름을 지정

lpCommandLine
명령행 인수를 지정함 첫번 인수가 NULL 경우 실행파일명을 가질 수도 있으며 실행 파일명과 명령행 인수를 동시에 지정하는 것도 가능하다.

lpStartupInfo
새로 만든 프로세스의 메인 윈도우가 어떻게 초기화될지를 지정하는 구조체이다.

lpProcessInformation
생성된 프로세스의 정보를 대입받기 위한 구조체이며 생략할 없다. 출력용 인수이므로 초기화 필요는 없고 구조체 변수를 선언한 번지만 전달하면 된다.

. 실행 정보

CreateProcess 함수는 프로세스 생성에 관한 세밀한 제어를 있는 함수이다.
아홉 번째 인수인 lpStartupInfo 비교적 크기가 구조체로 정의되어 있다.
typedef struct _STARTUPINFO { DWORD cb; LPTSTR lpReserved; LPTSTR lpDeskTop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; 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 ;

typedef struct _STARTUPINFO {
	DWORD cb;
    LPTSTR lpReserved;
    LPTSTR lpDeskTop;
    LPTSTR lpTitle;
    DWORD dwX;
    DWORD dwY;
    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 ;

구조체의 멤버들이 생성될 프로세스의 메인 윈도우 속성을 지정한다. cb 멤버에는  sizeof(STARTUPINFO) 값을 대입하여 버전을 밝히고 어떤 속성을 지정할 것인가에 따라 dwFlags 플래그를 설정하고 멤버에 적절한 값을 대입하면 된다.

플래그 설명
STARTF_FORCEONFEEDBACK 피드백 커서를 사용한다. 피드백 커서란 프로그램 초기화  나타나는 화살표 밑에 모래 시계가 있는 커서를 말한다.  커서는 사용자에게 프로그램 초기화중에도 다른 일을   있다는 것을 알린다.
STARTF_FORCEOFFFEDBACK 피드백 커서를 사용하지 않는다.
STARTF_RUNFULLSCREEN 콘솔 프로그램을 전체 화면 모드로 실행한다. GUI 프로그램에는 적용되지 않는다.
STARTF_USECOUNTCHARS dwCountChars 멤버로 콘솔 프로그램의 문자 폭을 지정하며 dwYCountChars 멤버로 문자 높이를 지정한다. GUI 프로그램에는 적용되지 않는다.
STARTF_USEFILLATTRIBUTE dwFillAttribute 멤버로 콘솔 프로그램의 전경, 배경 색상을 지정한다. 다음 값들의 조합으로 색상을 지정하되  플래그의 조합 값을 사용할  있다.
FOREGROUND_BLUE
FOREGROUND_GREEN
FOREGROUND_RED
FOREGROUND_INTENSITY
BACKKGROUND_BLUE
BACKGROUND_GREEN
BACKGROUND_RED
BACKGROUND_INTENSITY
GUI 프로그램에는 적용되지 않는다.
STARTF_USEPOSITION dwX, dwY 멤버가 지정하는 위치에 메인 윈도우를 배치한다.
STARTF_USEHOWWINDOW wShowWindow 멤버가 지정하는 방식대로 메인 윈도우를 보여준다.  멤버에는 SW_ 시작되는 상수중 하나를 지정한다.  값은 최초 ShowWindow 호출될  적용되며 이후부터 ShowWindow(hWnd, SW_SHOWDEFAULT) 호출될 때도 적용된다.
STARTF_USESIZE dwXSize, dwYSize 멤버가 지정하는 크기대로 메인 우니도우를 배치한다.
STARTF_USESTDHANDLES 표준 입력(hStdInput), 표준 출력(hStdOutput), 표준 에러(hStdError) 핸들을 지정한다. 이 핸들이 제대로 지정되려면 CreateProcess의 hInheritHandles가 TRUE로 지정되어야 한다.

GUI 프로그램에 대한 지정은 가지 박에 없다.
si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE ;
si.dwX = 100 ;
si.dwY = 50 ;
si.dwXSize = 640 ;
si.dwYSize = 480 ;
CreateProcess( NULL, "first.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ;

. 나머지 인수들

lpProcessAttributes, lpThreadAttributes
각각 새로 만들어지는 프로세스와 스레드의 보안 속성을 지정하는 SECURITY_ATTRIBUTES 구조체이다.
설정에 따라 리턴되는 핸들이 차일드 프로세스로 상속될 있는지가 결정된다. 인수가 NULL이면 디폴트 보안 속성이 지정되며 핸들은 상속될 없다.

bInheritHandles
새로 생성된느 프로세스가 페어런트로부터 핸들을 상속받을 있는지를 지정한다. 인수가 TRUE이면 상속가능한 열려진 핸들은 모두 차일드로 상속되며 상속된 핸들은 원래 핸들과 같은 , 같은 액세스 특권을 가진다. FALSE이면 핸들은 상속되지 않는다.

dwCreationFlags
새로 생성되는 프로세스의 우선 순위 클래스와 프로세스 생성 옵션을 지정한다. 여러 가지 옵션을 OR 연산자로 묶어 조합으로 지정할 있다. 우선 순위 클래스란 프로세스의 스레드가 얼마나 많은 CPU 시간을 할당 받을 것인가를 지정하는 플래그 이며 다음 하나를 지정할 있다.

플래그 설명
REALTIME_PRIORITY_CLASS 최상위 우선권
HIGH_PRIORITY_CLASS 상위 우선권
ABOVE_PRIORITY_CLASS 상위 우선권
NORMAL_PRIORITY_CLASS 보통 우선권
BELOW_PRIORITY_CLASS 하위 우선권
IDLE_PRIORITY_CLASS 최하위 우선권

프로세스의 우선순위를 구하거나 설정하는 함수
DWORD GetPriorityClass( HANDLE hProcess ) ;
BOOL SetPriorityClass( HANDLE hProcess, DWORD dwPriorityClass ) ;

DWORD GetPriorityClass(HANDLE hProcess);
BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass);

lpEnvironment
프로세스의 환경 블록을 지정하는 포인터이다. 값이 NULL이면 페어런트의 환경 블록을 사용하면 보통 NULL 사용한다.

lpCurrentDirectory
프로세스의 작업 디렉토리를 지정한다. 프로세스는 인수가 지정하는 경로를 현재 디렉토리로 인식하는데 주로 프로그램에서 응용 프로그램을 실행시킬 인수가 사용된다. 작업 디렉토리로 지정할 완전 경로 문자열을 전달하되 인수가 NULL 경우 페어런트의 현재 디렉토리가 프로세스의 작업 디렉토리로 사용된다.

. FindProc

단순히 프로세스를 생성하기만 목적이라면 WinExec 사용하는 것이 훨씬 편리하다.
사실 WinExec 내부적으로는 CreateProcess함수를 호출한다.
그러나 WinExec CreateProcess 함수는 중요한 차이점이 있는데 바로 리턴 시기이다.
CreateProcess 함수는 프로세스를 생성한 곧바로 리턴하므로 실행 중인 프로그램이 초기화 중이며 메인 윈도우가 만들어져 있지 않다. 따라서 FindWindow함수는 윈도우를 찾지 못한다.
WinExec 초기화될 때까지 기다렸다가 리턴하므로 FindWindow 의해 윈도우를 찾을 있다.

만약 프로세스를 생성한 메시지를 전달하거나 IPC 데이터를 교환하고자 한다면 위와 같은 CreateProcess 함수 호출로는 원하는 결괄르 얻을 없다. 때는 프로세스를 생성한 직후에 다음 함수를 호출해야 한다.

DWORD WaitForInputIdle( HANDLE hProcess, DWORD dwMilliseconds ) ;

함수는 hProcess 지정하는 프로세스가 사용자의 입력을 받을 있을 때까지, 초기화가 완료될 때까지 또는 dwMilliseconds 인수가 지정하는 시간이 경과될 때까지 대기한다.
CreateProcess 함수의 이런 특성을 모르면 골치아픈 버그의 원인이 수도 있다. 왜냐하면 특성은 짧은 순간에만 나타나므로 디버그 과정에서는 목격되지 않기 때문이다. 단계 실행을 때는 디버거에 의해 호출 프로세스가 자연스럽게 대기를 하게 되므로 이런 현상을 목격할 없다.

. ShellExecute

프로세스를 생성하는 다른 함수로 ShellExecute 있다. 함수는 운영체제가 직접 제공하는 함수가 아니라 쉘이 제공하는데 탐색기는 항상 설치되므로 언제든지 사용할 있는 기본함수와 마찬가지이다.

HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd ) ;

HINSTANCE ShellExecute(
	HWND hwnd,
    LPCTSTR lpOperation,
    LPCTSTR lpFile,
    LPCTSTR lpParameters,
    LPCTSTR lpDirectory,
    INT nShowCmd);

함수는 실행 파일 뿐만 아니라 일반 데이터 파일도 실행할 있다. 데이터 파일을 실행하면 보통 연결된 프로그램이 실행되면서 데이터 파일이 같이 열린다. 예를 들어 txt파일을 실행하면 텍스트 파일을 편집할 있는 편집기가 열리는데 통산 메모장이 실행된다.
hwnd 부모 윈도우의 핸들인데 프로세스 실행 중에 열리는 에러 메시지 박스가 윈도우의 차일드로 생성된다. 번째 인수로 해당 파일을 어떻게 것인가를 지정하는 동사(Verb) 문자열 형태로 지정한다.

동사 설명
open 파일을 연다. 실행 파일일 경우 곧바로 실행되며 데이터 파일은 연결된 프로그램이 실행된다.
edit 편집기를 열어 편집한다. 데이터 파일만 있다.
explorer 폴더를 연다.
print 문서 파일을 인쇄한다.
NULL 디폴트 동사를 실행한다. 통산 "open"또는 레지스트리의  번재 동사가 사용된다.

02 프로세스 관리

. 명령행 인수

명령행 인수란 프로그램이 운영체제(또는 )로부터 받아들이는 일종의 인수이다. 프로그램의 작업거리를 전달받는다는 점에서 도스에서와 기능적으로 동일한 의미를 가진다.명령행 인수는 공백으로 분리된 여러 개의 문자열로 구성되는데 여러개의 인수가 전달될 경우 응용 프로그램은 명령행 인수를 토큰별로 분리한 사용한다. 명령행 인수를 어떤 용도로 사용할 것인가는 프로그램이 정하기 나름이다.
프로그램 실행 중에 명령행 인수를 읽어야 필요가 있으면 언제든지 다음 함수를 호출한다.

LPTSTR GetCommandLine( VOID ) ;

함수는 현재 프로세스의 명령행 인수를 조사해 리턴한다. 프로그램의 완전경로와 명령행 인수 전체를 하나의 문자열로 리턴하므로 사용하기는 불편한다. 그러나 함수는 유니코드로 전달되는 명령행 인수도 읽을 있고 필요할 언제든지 호출할 있다는 장점이 있다.
유니코드로 전달된 명령행 인수를 다음 함수를 사용하여 토큰별로 분리할 수도 있다.

LPWSTR *CommandLineToArgvW( LPCWSTR lpCmdLine, int * pNumArgs ) ;

GetCommandLineW 함수로 조사한 명령행 인수를 함수의 번째 인수로 전달하고 정수형 변수의 포인터를 전달하면 내부에서 메모리를 할당하여 토큰 배열을 작성하고 배열의 시작 번지를 리턴한다. 번지를 p 받았다면 p[0] 프로그램의 이름이 되고 p[1], p[2]에는 인수들의 시작 번지가 전달된다. pNumArgs에는 인수의 개수가 대입된다. 함수가 할당한 메모리는 LocalFree 해제해야 한다.

. 프로세스의 종료

C 런타임 코드는 다음 함수를 호출하여 정리작업을 수행한다.

VOID ExitProcess( UINT uExitCode ) ;

함수가 호출되면 프로세스는 정리작업에 들어가 즉각 종료된다. 프로세스가 종료될 때는 다음 일련의 작업이 이루어진다. 프로세스를 생성하는 절차가 복잡한만큼 정리해야 것도 많다.

  1. 프로세스와 연결된 모든 DLL 종료시키기 위해 DLL DllMain함수가 호출되며 DLL들은 스스로 정리작업을 한다.
  2. 모든 열려진 핸들을 닫는다.
  3. 실행중인 모든 스레드를 종료한다.
  4. 프로세스 커널 객체와 스레드 객체는 신호상태가 되며 객체를 기다리는 다른 프로세스는 대기 상태를 해제할 있다.
  5. 프로세스의 종료코드는 STILL_ACTIVE에서 ExitProcess 지정한 종료값이 된다.
BOOL TerminateProcess( HANDLE hProcess, UINT uExitCode ) ;

함수는 ExitProcess 비해 종료 대상이 되는 프로세스의 핸들을 인수로 가지므로 자기 자신이 아닌 다른 프로세스를 강제로 종료시킬 수도 있다.
그러나 함수는 ExitProcess보다 훨씬 위험하다. TerminateProcess 함수가 호출될 ExitProcess 동일한 정리 작업이 수행되나 연결된 DLL에게 종료사실이 통지되지 않는다.
함수를 정상적인 프로세스의 종료에 사용하는 것은 바람하지 않으며 어쩔 없이 강제로 종료해야 경우에만 사용해야 한다.

. 프로세스 핸들

윈도우즈는 GDI, USER, KERNEL 가지 주요 DLL 구성되어 있다. 모듈은 여러 종류의 객체를 관리하며 관리의 편의를 위해 핸들을 사용한다. 객체는 시스템 리소스를 나타내는 일종의 데이터 구조체이며 구조체들은 보통 덩치가 크기 때문에 간단한 32비트 정수값의 핸들로 관리된다.

모듈 객체 특징
USER 윈도우, 커서, 캐럿, 아이콘 한 오브젝트에 하나의 핸들, 시스템 전역적
GDI 펜, 브러시 비트맵, 팔레트 한 오브젝트에 하나의 핸들, 프로세스 지역적
KERNEL 파일, 프로세스, 스레드, 이벤트 보안 적용, 프로세스 한정적

USER 객체는 윈도우 관리에 사용되며 시스템 전역적이라는 특징이 있다. ProcA에서 윈도우를 하나 만들면 윈도우 핸들이 주어지는데 핸들을 ProcB 전달하면 ProcB 윈도우 핸들을 사용하여 ProcA 만든 윈도우를 마음대로 요리할 있다. 시스템 전역적이라는 말은 어떤 프로세스든 핸들만 가지면 USER 객체를 액세스 있다는 말이다. USER 객체는 오브젝트에 하나의 핸들만 주어진다. 하나의 윈도우를 가리키는 핸들은 오직 하나뿐이다.
GDI 객체는 그래픽을 위해 사용되는데 해당 객체를 만든 프로세스 내에서만 사용할 있다. ProcA에서 펜을 만들고 hPen 핸들을 발급받았다고 하자. 핸들은 오직 ProcA에서만 의미가 있을 뿐이지 ProcB에게 핸들을 전달한다고 해서 ProcB 펜을 사용할 있는 것은 아니다. GDI 오브젝트는 언제든지 원하는 대로 생성할 있는데다 공유할 필요가 없기 때문에 프로세스 지역적이다.
커널 객체는 메모리 관리, 프로세스 관리, IPC, 동기화 등에 사용되는 객체인데 장의 주제인 프로세스와 스레드도 커널 객체이다. 커널 객체는 USER객체나 GDI 객체와는 다른 특징들을 많이 가지고 있으며 다소 저수준이므로 이해하기도 약간 어렵다. 그러나 커널 객체는 시스템과 밀접한 연관을 가지고 있으므로 운영체제를 이해하는데 아주 중요하다.
커널 객체는 보안상의 권리가 있는 프로세스만 만들 있다. 윈도우나 비트맵은 어떤 프로세스나 자유롭게 만들 있지만 프로세스나 파일 객체는 권리가 있어야만 만들거나 있다. 윈도우즈는 멀티 유저를 지원하는데 파일이나 프로그램 모두 소유자를 지정할 있고 소유자만 액세스하도록 권한을 설정할 있다. 그래서 커널 객체를 만드는 CreateProcess, CreateFile, CreateMutext 등의 함수들은 모두 보안 속성(LPSECURITY_ATTRIBUTES) 인수로 가진다.
이런 보안상의 이유로 커널 객체는 프로세스 한정적(Process Specific)이다. 이말의 정확한 뜻은 커널 객체를 만든 프로세스만이 자신이 받은 핸들로 해당 객체를 액세스 있다는 뜻이며 핸들을 다른 프로세스로 전달하는 것은 의미가 없다.

ProcB ProcC 있는 권한이 있는지 아직 확인하지 않았기 때문이다. ProcB ProcC 액세스하고 싶다면 다음 함수로 프로세스의 ID로부터 프로세스 핸들을 다시 열어야 한다. 경우는 핸들을 보안 속성을 다시 지정하며 프로세스의 액세스 토큰을 분석하여 권한이 있는지 확인한다.

HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessID ) ;

핸들이 무사히 열리면 ProcB 새로 발급받은 hp2 ProcC 액세스 있다. 이때 핸들 hp hp2 같은 객체를 가리키지만 서로 값은 다를 수도 있다. 객체를 가리키는 핸들이 이상 존재할 있다.
핸들은 만든 프로세스에서만 의미가 있으므로 다른 프로세스에게 전달해 봐야 없다. 그래서 프로세스 객체는 핸들 외에 ID라는 식별자를 추가로 가진다. CreateProcess 마지막 인수를 다시 보자.

typedef struct _PROCESS_INFORMATION {
	HANDLE hProcess;
    HANDLE hThread;
    DWORD dwProcessId;
    DWORD dwThreadId;
}PROCESS_INFORMATION ;

구조체에는 프로세스 핸들값인 hProcess ID값인 dwProcessId 가지가 있으며 이는 스레드도 마찬가지다. 핸들은 프로세스 내에서 해당 객체를 액세스할 사용하는 한정적인 값이며 핸들을 사용하여 객체를 마음대로 조작할 있다. 반면 ID 시스템 전역적인 값이며 다른 프로세스 ID 절대 중복되지 않는다. 그래서 프로세스끼리 ID 전달함으로써 목적이 되는 프로세스 핸들을 다시 오픈할 있다.
프로세스 ID 프로세스간의 구분을 위한 중복되지 않는 식별값일 뿐이며 ID로부터 직접 프로세스를 제어할 수는 없다. ID로부터 핸들을 발급받아야만 비로소 객체를 제어할 있다.

커널 객체는 여러 프로세스에서 동시에 참조할 있기 때문에 참조 카운트(Usage Count) 유지된다. 그래서 사용 후에는 반드시 CloseHandle 핸들을 닫아야 하는데 만약 프로세스를 생성한 특별히 핸들을 닫아 버리는 것이 좋다.

if (CreateProcess(NULL, "NotePad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
	CloseHandle(pi.hProcess) ;
	CloseHandle(pi.hThread) ;
}

핸들과 대상은 일체성이 있을 수도 있고 없을 수도 있는데 대부분의 핸들은 일체성이 있다. 윈도우나 , 동기화 객체 등은 핸들을 닫으면 대상체도 즉시 파괴된다. 그러나 프로세스, 스레드, 파일은 핸들과 대상의 일체성이 없어서 핸들과 대상이 별개이다. 가장 쉬운 예로 파일을 열어서 액세스 닫았다고 했을 이는 파일에 대한 액세스가 끝났다는 것이지 파일 자체를 지우라는 것은 아니다.

다음 함수는 현재 프로세스의 핸들과 ID 구한다.

HANDLE GetCurrentProcess(VOID);
DWORD GetCurrentProcessId(VOID);

다음 함수는 프로세스의 종료 상태를 구한다.

BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);

BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);

인수로 프로세스의 핸들을 주면 프로세스의 종료 상태를lpExitCode 리턴한다. 프로세스가 아직 종료되지 않았다면 STILL_ACTIVE 되며, 종료되었다면 다음 하나가 된다.
ExitProcess TerminateProcess함수의 인수
main이나 WinMain 리턴한
처리되지 못한 예외값

다음 함수는 모듈의 핸들과 경로명을 구하는데 주로 프로세스 자신의 핸들과 경로를 조사할 사용된다.

HMODULE GetModuleHandle(LPCTSTR lpModuleName);
DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFileName, DWORD nSize);

 

반응형

'책정리 > 윈도우 API 정복2' 카테고리의 다른 글

41장 멀티 스레드  (0) 2019.04.16
39장 메모리  (0) 2019.04.04
39장 메모리  (0) 2019.04.03
34장 시스템 정보  (0) 2019.03.19
목차  (0) 2019.03.03