프로그래밍을 통한 프로세스의 생성


프로세스 생성 함수



BOOL CreateProcess(

LPCTSTR lpApplicationName ,   //실행파일 이름 지정

LPTSTR lpCommandLine ,          /*매개변수 전달  (실행파일이름과 매개변수                            

                                                     정보를 묶어서 하나로 이곳에 표현 가능)*/

LPSECURITY_ATTRIBUTES lpProcessAttributes ,

LPSECURITY_ATTRIBUTES lpTreadAttributes ,

BOOL binheritHandles ,

DWORD dwCreationFlags ,

LPVOID lpEnvironment ,

LPCTSTR lpCurrentDirectory ,

LPSTARTUPINFO lpstrartupInfo ,

LPPROCESS_INFORMATION lpProcessInformation

);




LPSTARTUPINFO 

 정보전달

CreateProess 

정보반환

  LPPROCESS_INFORMATION 


※CreateProcess함수를 호출하기 위해서는

 LPSTARTUPINFO, LPPROCESS_INFORMATION 구조체를 선언해야한다.


LPSTARTUPINFO

이구조체를 통하여 생성하고자하는 프로세스 특성정보를 설정하여 CreateProcess에 인자로 전달한다.

 

LPPROCESS_INFORMATION 

CreateProcess함수가 생성된 프로세스정보를 LPPROCESS_INFORMATION 에 반환한다.




LPSTARTUPINFO


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 dwFileAttribute;

DWORD dwFlags;    //설정된 멤버의 정보

WORD wShowWindow;

WORD cbReserved2;

LPBYTE lpReserved2;

HANDLE hStdInput;

HANDLE hStdOutput;

HANDLE hStdError;

} STARTUPINFO, *LPSTARTUPINFO;


LPPROCESS_INFORMATION


typedef struct _PROCESS_INFORMATION

{

HANDLE hProcess;        //프로세스의 핸들

HANDLE hThread;         //쓰레드 핸들

DWORD dwprocessId;    //프로세스의 ID

DWORD dwThreadId;      //쓰레드ID

} PROCESS_INFORMATION;

DWORD cb; 를 보면 구조체의 크기인데 왜 구조체가 정해져잇는데 구조체의 크기를 인자로 전달하는 걸까?

CreateProcess 함수를 보면 9번째 인자는 LPSTARTUPINFO로 확정되어있다.

그런데 나중에 다른인자를 올수있게 라이브러리를 개편한다면 전과의 호환성을 위해 구조체를 구별 할 수있게 전달하는 것이다.



예제 5-1]



AdderProcess 자식프로세스 단순덧셈프로세스

CreateProcess 부모프로세스 AdderProcess를 실행시키는 예제이다.


표준 검색경로

1 실행중인 프로세스의 실행파일이 존재하는 디렉터리

2 실행중인 프로세스의 현재 디렉터리(Current Directory)

3 Windows의 시스템디렉터리 (System Directory)

4 Windows 디렉터리 (Windows Directory)

5 환경변수 PATH에 의해 지정되어 있는 디렉터리




실행결과

 







프로세스와 스케줄러의 이해


프로세스의 이해

 

프로세스란?

메인 메모리로 이동하여 실행중인 프로그램 → 일반적인 정의

보통 프로세스라 하면 실행중인 프로그램 이다. 라고 표현을 한다.

틀린 표현은 아니다. 

그러나 메인메모리가 256메가 인데 실행파일의 크기가 1기가 라고 하면 과연 메모리에 올라가있는 코드만 프로세스인가? 

틀린건 아니지만 너무 애매한 표현이다.



프로세스의 구체적인 이해


프로세스의 범위

메모리 구조 + 레지스터 Set

프로세스 별 독립적인 대상은 프로세스의 범주에 포함시킬 수 있다.




 ↑

 Code 영역

명령어

(Instruction Code)

   

 ↑

Data 영역

 전역변수

static 변수

   

Heap 영역



Stack 영역

 프로그래머 할당

   

 



   

 지역변수

전달인자 정보

   
       

프로세스가 생성되면 위와같은 메모리가 할당 된다. 

프로그램이 실행된다라는 것은 레지스터에 프로그램 실행정보로 가득차게되는데

이런 레지스터 set과 메모리 구조 모두 프로세스 범위에 포함된다.


'프로세스를 구성하는 범주는 프로세스 별로 독립적으로 할당받는 리소스다.'

라고 할 수 있다.



프로세스 스케줄러


프로세스 스케줄러 기능

둘 이상의 프로세스가 적절히 실행되도록 컨트롤


스케줄링 방법

스케줄링 알고리즘에 따라 다양함.



스케줄러 라는 장치는 Windows 에서 지원해주는 소프트웨어적인 장치이다.

프로세스 스케줄러는 말그데로 프로세스를 스케줄링 해주는 것이다.

CPU는 하나인데 프로세스는 여러게를 실행 시키려하면 CPU는 하나의 프로세스만 실행시킬수 있기때문에 스케줄러가 프로세스의 순서를 정해주고  순서를 정하는 정책을 결정하고 관리해주는 것이다.


§스케줄러는 소프트웨어이기 때문에 스케줄러가 동작하는 순간에도 프로세스들은 동작하지 못한다. 넓은 관전에서 보면 스케줄러도 프로세스에 포함시킬 수 있다.






프로세스의 상태




프로세스는 Ready , Running, Blocked 같은 상태정보를 지닌다.

Running 상태는 CPU에 의해서 실행중인 상태로 CPU가 하나라면 Running 상태의 프로세스는 하나일 수 밖에 없다.

Blocked는 실행중이 아닌 상태.

Ready 상태는  Running 하고 싶은 상태로 C프로세스가  Running 상태이고

A와 B가 Ready 상태일때 C가 Blocked 상태로 간다고 하면 A와 B중 누가 Running

상태로 가느냐를 정해주는 것이 바로 스케줄러가 하는것이다.   

즉 Ready 상태에 있다는 것은 스케줄러가 선택해주기를 기다리는 상태이다.

그림에서 볼 수있듯이 모든 프로세스는 실행시키면 Ready 상태가 된다.

연산중에는 CPU에 의존적인 연산이 있고 그렇지 않은 연산있다.

그중에 I/O연산은 유독 CPU에 의존적이지 않기때문에 사칙연산과같은 기본적인 연산과 병행해 질수있다. 

만약에 Running 상태에 있는 C라는 프로세스가 I/O 연산시작 했을때 I/O 연산이 끝날때 까지 C는 쉬고있고 대신 다른 프로세스가  Running 상태가 되어도 된다.

그럼 C는 Ready 상태가 되야될까? Blocked 상태가 되야할까?

 Ready 상태가 된다고 생각해보면 C는 다시  Running 상태가 될것이고 I/O연산이 끝나지 않았다면 다시  Ready 상태가 되는 반복을 하기때문에 Blocked 상태가 된다.

그리고 다시 I/O연산이 끝났다면 Ready 상태로 돌아가게 된다.

 Running 상태에서 바로 Ready 상태가 되는것은 다른 프로세스들고 실행을 시키여하기때문에 연산이 끝나지않았어도 Ready 상태로 내리는 경우이다.


1. 모든 프로세스는 실행시키면 Ready 상태가 된다.

2. Ready 상태이면 스케줄러가   Running 상태로 만들어준다.

3. Running 상태에서 다른 프로세스를 실행시키기위해 어쩔수 없이 양보하는 경우

    Ready 상태로 내려간다.

4. 일반적으로 I/O 연산을 하고있는 프로세스들은 다른프로세스들에게 양보하기위        

   해서 Blocked 상태로 간다.

5. I/O 연산이 끝나면 프로세스를 다시 진행시키기위해  Ready 상태가 된다.

6. 프로세스 종료.




컨텍스트 스위칭(context switching)




ALU가 연산을 하기위해서 레지스터에 의존적이다.

레지스터는 Running 상태의 프로세스 정보로 가득차있다.

이때 Ready상태의 프로세스를 실행 시키려 할때 프로세스를 실행시킬 수 있는 

첫 번째 조건은 지금 레지스터레 채워져있는 데이터를 다른 저장영역에 저장시키고

 Ready상태의 프로세스를 위한 데이터를 레지스터에 복원해야한다.

이런 작업을 컨텍스트 스위칭(context switching)이라 한다.













Direct 모드와 Indirect 모드


Direct 모드                              Indirect 모드          

  LOAD r1, 0x10 실행시                LOAD r1, [0x10] 실행시              

 r0

 

 r0

 
 r1

 ←10     0x10번지

 r1

 0x30                  ↓                 0x10번지

 r2   r2

   ↖                   ↓

 r3

  r3

       ↖   10                            0x30번지

 r4     ir

 

 r4     ir

 
 r5     sp  

 r5     sp

 
 r6     lr  

 r6     lr

 

 r7     pc

 

 r7     pc

 


Direct 모드는 말그데로 메모리에 있는 값을 레지스트로 가져와라 이고

Indirect 모드는  메모리에 있는 값을 다시 메모리로 참조에서 값을 가져오는것이다.  0x10[0x30] → 0x30[10] → r1

※  LOAD r1, [0x10] 여기서 []는 Indirect 모드 라는 표시로 아무거나 써도 상관은없다.



Direct 모드의 문제점


 

 <-  LOAD  ->

 <destination>

<-                    source                   ->

 0

 0

 1

1

0

 0

1

 1

 0

 0

 0

1

 1

 1

   

int a = 10;      //0x0010 번지할당

int b = 20;     //0x0100 번지 할당

int c = 0;       //0x0020 번지 할당

c = a + b;

                                                                                      

LOAD r1, 0x0010 (구성가능)

LOAD r2, 0x0100 (구성불가)


8비트로 표현가능한 수는 0~255이다.

LOAD 명령어를 살펴보면 source 부분은 8비트 밖에 되지않는다.

0x0010같은 경우는 8비트로 표현이 가능하지만 0x0100은 딱봐다 8비트로는 표현이가능하지않는다. 

그럼 명령어로 구성 할 수없는 메모리 주소는 어떻게 사용할 것이가??



문제해결


int a = 10;      //0x0010 번지할당

int b = 20;     //0x0100 번지 할당

int c = 0;       //0x0020 번지 할당

c = a + b ;

명령어로 표현해보면 메모리 주소값문제로 Direct 모드로 표현 할 수없다는 것을 알고있다.

그래서 Indirect 로 풀어보면 


LOAD r1 , 0x0010


MUL r0, 4, 4

MUL r2, 4, 4
MUL r3, r0, r2


STORE r3, 0x0030

LOAD  r2, [0x0030]


ADD r3, r1, r2

 일단 r1에 a값을 넣는것은 그냥 LOAD명령어를 넣으면 된다 

하지만 b값은 메모리주소 0x0100 에 할당되어있어서 명령어로 표현이 불가능하다 그래서 MUL 명령어를 이용해보자.

r0에 4 곱하기 4 연산값을 넣고 r2에도 반복하자.

그리고 r3에 r0와 r2의 값을 곱한값을 넣으면 16*16 즉 256 , 16진수로 0100 이다. r3에보면 0x100이 들어가 있는상태이다.

이제 r3에 있는 값을 0x0030 번지에 값을 넣고 Indirect로 0x0030을 불러와서 r2에 넣으면 r2에 원하던 값을 넣을 수 있게 된다 .


     레지스터                                 메모리

 r0         16

 

 r1         10

   10                                 0x0010(a)

 r2         16

   0                                  0x0020(c)

 r3     265(0x0100)

   
 r4   ir

  0x0100                               0x0030

 r5   sp

  20                                      0x0100

 r6   lr  
 r7   pc  


그림으로 만들어 보면 이런 모양일 것이다.



+ Recent posts