프로세스는 서로 만나지 못한다. --------------------------------------------------------------------------------

일반적으로 프로세스는 CPU안에서 동시에 실행되는것이 불가능 하다. 그 이유는 프로세스가 메인메모리에서 차지하는 영역은 서로 독립되어 있기 때문이다.

이런 식으로 서로간의 프로세스의 메모리 영역이 다르니 서로간에 절대 만날 수 없다. 윈도우시스템의 프로세스가 이와 같이 디자인된 이유는 간단하다. CPU의 메모리 영역상에서 하나의 프로세스만 실행되는것이 당연히 안정성이 더 높기 때문이다.


IPC 프로세스가 서로간에 교류할 수 있는 방법. --------------------------------------------------------------------

당연히 프로세스간 교류가 필요한 경우가 있을 것이다. 그런 경우를 위해서 윈도우시스템에서는 몇가지 프로세스간 통신방식을 지원하고 있고 그것을 IPC(inter-process-Communication)라고 한다.


IPC 의 종류. ------------------------------------------------------------------------------------------------

메일슬롯방식 : 단방향 통신 한쪽으로만 명령어를 보낼수 있고 메일슬롯이란 새로운 리소스를 생성하여 그곳을 통해서 한쪽 방향으로만 서로간의 정보 교환이 가능하다.


파이프방식 : (이름없는 파이프)Anonymous Pipe 방식과 (이름있는)Named Pipe방식이 존재한다.

간단히 설명하자면

(이름없는 파이프)Anonymous Pipe -> 이름이 없다. 즉 특별한 주소가 없다. 그러므로 이미 서로를 알고 있는(서로의 핸들이나 주소값을 알고 있거나 상속관계나 포함관계에 있는) 프로세스들 사이에서 사용이 될 수 있다.

(이름있는)Named Pipe -> 이름이 있다. 즉 자신의 주소가 있어 그 주소를 알고 있는 아무런 관련없는 프로세스 간에도 통신이 가능한 방법이라고 생각하면 된다.


한번더 정리. -----------------------------------------------------------------------------------------------

메일슬롯 : 브로드캐스트(Broadcast) 방식의 단방향 통신방식 메일슬롯에 할당된 주소를 기반으로 통신하기 때문에 관계없는 프로세스들 간에도 통신이 가능하다.

이름없는 파이프 : 단방향 통신방식을 취하여, 파이프를 통해서 생성된 핸들을 기반으로 통신하기 때문에 프로세스들 사이에는 관계가 있어야만 한다.

이름있는 파이프 : 메일슬롯과 유사하다. 차이가 있다면, 브로드캐스트 방식을 지원하지 않는 대신 양방향 통신을 지원한다.



핸들 테이블 -------------------------------------------------------------------------------------------------

핸들 테이블은 프로세스의 핸들정보를 저장하고 있는 테이블로서 프로세스별로 독립적이다. 하지만 자식프로세스가 부모 프로세스의 일부를 상속받는 경우도 있다. 이는 CreateProcess함수 핸들 상속 인자값등에서 확인이 가능하다.



Posted by JJOREG

커널? 커널 오브젝트? -----------------------------------------------------------------------------------------

커널은 운영체제를 이루는 핵심적인 부분을 의미하며 커널에서 관리하는 중요한 정보들을 담아둔 데이터 블록을 커널 오브젝트라고 한다.

새 프로세스가 생성될때마다 그 프로세스에 대한 정보를 담아둘 구조체가 생성되고 이 구조체들은 당연히 그 프로세스의 정보들로 초기화 되게 되는데 이것이 커널 오브젝트(Kernel Object)의 정체이다.


커널 오브젝트는즉 윈도우 커널에서 관리해야한다고 판단한 프로세스나 기능, 파일등에 커널오브젝트가 생성되며 당연히 그 종류에 따라서 적합한 커널오브젝트 구조체를 생성한다.


오브젝트 핸들? -----------------------------------------------------------------------------------------------

그렇다면 플레이어는 이런 커널오브젝트에 관여할 수 있을까? 마이크로소프트에서는 프로그래머가 제한적이지만 커널오브젝트에 접근할수 있게 하기위한 함수를 제공하고 있으며 이 커널오브젝트에 접근 할수 있는 인자값인 핸들을 통해서 간접적인 접근이 가능하다.

즉 핸들이라는 키를 통해서 커널오브젝트라는 여러개의 방이 있는 건물에 들어가 들어갈 수 있는 곳의 내용은 변경이 가능하다는 이야기 이다.

"저기 저 커널오브젝트 핸들을 이러이러 저러저러 해주세요"

핸들이 있어야만 어떤 커널오브젝를 지칭하는 것인지 윈도우에게 알릴 수 있는 것이다.


커널 오브젝트의 종속관계? -------------------------------------------------------------------------------------

커널 오브젝트는 윈도우 운영체제에 종속적이다..

프로세스의 기준으로 커널 오브젝트는 프로세스의 정보를 담고 있지만 커널오브젝트를 관리하는 것은 프로세스가 아닌 윈도우 운영체제라고 생각하면 된다. 그러므로 각 프로세스는 하나의 커널오브젝트를 공유할수도 있다.


Usage Count? ----------------------------------------------------------------------------------------------

Usage Count란 하나의 커널오브젝트가 생성되면 그 커널오브젝트를 참조하는 프로세스의 수를 의미한다. 모든 커널 오브젝트는 생성시 1의 Usage Count를 가지게 되고 다른 프로세스가 커널오브젝트 자신을 참조하게 되면 Usage Count를 1씩 증가시킨다.

Usage Count가 중요한 이유는 다음과 같다.

모든 커널 오브젝트는 Usage Count가 0이 되어 자신을 참조하는 녀석이 아무도 없을때 소멸되기 때문이다. 그리고 커널 오브젝트의 참조는 위에서 핸들을 통해서 한다고 했으므로 참조를 그만둔다는 명령어는 곧 그 커널오브젝트의 핸들을 닫는다는 CloseHandle를 통해서 작동하게 된다.

즉 어떤 프로세스든 일단 띄우면 Usage Count가 2가 된다. 

이유는 윈도우나 바탕화면에 있는 아이콘은 이미 Usage Count가 1인 상태다. 바탕 화면 그 자체가 이미 그 프로그램에 대한 핸들을 가지고 있다고 봐야 하니까.

그리고 윈도우가 완전히 종료되어야 Usage Count가 0이 되어 모든 프로세스가 정상적으로 종료하게 된다.


커널 오브젝트의 2가지 상태 ------------------------------------------------------------------------------------

커널 오브젝트는 2가지 상태가 존재하는데 하나는 Signaled 상태(신호를 받은 상태) 또하나는 Non-Signaled 상태(신호를 받지 않은 상태)가 존재한다.
그리고 대부분의 사물과 마찬가지로 특정상황 하에서 커널 오브젝트의 상태는 전환될수 있다.
이러한 상태값은 커널오브젝트를 구성하는 멤버변수 중 하나에 저장되어 있으며 이 맴버변수는 Signaled 상태(신호를 받은 상태)일때는 TRUE Non-Signaled 상태(신호를 받지 않은 상태)에서는 FALSE가 된다.

처음 커널 오브젝트가 생성되면 그 상태는 신호를 Non-Signaled상태가 되며 프로세스가 종료되면 자동으로 Signaled상태가 된다. 그리고 프로세스는 종료되면 그 실행을 종료하므로 한번 종료된 프로세스는 처음부터 다시 실행되기 전가지는 항상 Signaled상태를 유지하게 된다.



커널 오브젝트의 종료코드 -----------------------------------------------------------------------------

프로세스는 종료시 자신의 종료코드를 커널오브젝트에 넘긴다. 이 종료코드는 커널오브젝트의 핸들을 참조할수 있는 부모 프로세스에 메세지를 전달하는 방식으로 이용될 수 있다.

이때 사용되는 함수는 GetExitCodeProcess함수를 이용할수 있다.

또한 각기의 프로세스는 동기화가 되어있지 않으므로 프로그래머가 원하는 경우가 나오지 않을수가 있는데. 이때를 위해서 자식 프로세스가 완전히 연산을 마칠때가지 기다려주는 함수로 WaitForSingleObject함수가 존재한다.




Posted by JJOREG

프로세스 생성 함수 -------------------------------------------------------------------------------------------

윈도우에는 CreateProcess함수가 있다.

이 크리에이트 프로세스를 사용하여 프로세스를 생성하는 프로세스를 가리켜 부모 프로세스(Parent Process)라고 하고 이 함수를 통해서 생성된 프로세스를 자식 프로세스(Child Process)라고 한다.


함수의 원형을 살펴보자.

BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);

뭔가... 많다. 인자값을 한번 살펴보자.

------------------------

1. __in_opt LPCTSTR lpApplicationName,                  

-> 생성할 프로세스의 실행파일 이름을 인자로 전달.

------------------------

2. __inout_opt LPTSTR lpCommandLine,                    

-> main 함수에 있는 argc, argv라는 이름으로 문자열의 개수와 문자열이 전달된다. 1.번을 NULL로 했을경우 이곳에서 실행파일의 이름을 전달할 수도 있다. 이러한 경우 실행파일의 이름은 표준검색경로를 기준으로 찾게 된다.

------------------------

3. __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,

-> 프로세스의 보안속성을 지정한다. NULL로 선언하면 Default속성으로 지정된다.

------------------------

4. __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,

-> 쓰레드의 보안속성을 지정할때 사용된다. NULL을 전달할 경우 Default속성으로 지정된다.

------------------------

5. __in BOOL bInheritHandles,

-> 전달인자가 TRUE인경우 생성되는 자식 프로세스는 부모프로세스가 소유한 핸들중 일부(상속가능한 녀석들)을 상속한다.

------------------------
6. __in DWORD dwCreationFlags,

-> 생성하는 프로세스의 특성(특히 우선순위)을 결정지을 때 사용되는 옵션이다. 일반적으로 0으로 설정한다.

------------------------
7. __in_opt LPVOID lpEnvironment,

-> 프로세스마다 Environment Block 라는 메모리 블록을 관리한다. 이블록을 통해서 프로세스가 실행에 필요로 하는 문자열을 저장할수 있다. NULL로 지정할 경우 자식프로세스는 부모프로세스의 환경 블록에 저장되어 있는 문자열을 복사하게 된다.

------------------------
8. __in_opt LPCTSTR lpCurrentDirectory,

-> 생성하는 프로세스의 현재 디렉토리를 설정한다. 인자는 디렉토리 정보를 포함하는 완전 경로 형태로 구성되어야 한다. NULL이 전달될 경우 부모프로세스의 현재 디렉토리가 새로 생성하는 자식 프로세스의 현재 디렉토리가 된다.

------------------------

9. __in LPSTARTUPINFO lpStartupInfo,

-> STARTUPINFO 구조체 변수를 초기화한 다음 이 변수의 포인터를 인자로 전달한다. STARTUPINFO내용은 추후 설명

------------------------

10. __out LPPROCESS_INFORMATION lpProcessInformation

-> 생성하는 프로세스 정보를 얻기 위해 사용되는 인자이다. PROCESS_INFORMATION구조체 변수의 주소값을 인자로 전달한다.

------------------------


현재디렉토리(Current Directory)? ------------------------------------------------------------------------------

#include <iostream> 같은 전처리 명령등에서 완전경로(c: 에서부터 지금 사용하려면 파일이나 폴더가 있는 경로를 모두 포함한 값)를 사용하지 않고 파일 참조가 가능했다.

현재디렉토리라는 개념은 일반적으로 실행하려는 프로그램의 실행파일이 존재하는 폴더를 의미한다.

DWORD GetCurrendtDirectory(DWORD nBufferLength, LPTSTR lpBuffer) 함수로 확인이 가능하다.

첫번째는 두번째 인자값의 무낮열 길이를 정보를 넣고 두번째 정보는 정보를 담을 문자열 포인터를 넣으면 된다.

현재 디렉토리는 BOOL CurrendtDirectory(LPCTSTR lpPathName) 함수로 선언이 가능하고 변경하길 원하는 디렉토리 경로명만 넣으면 된다.


Posted by JJOREG