728x90

운영체제가 커널 오브젝트 소멸 시점을 결정하기 위해서는 일단 프로세스가 종료되어야 한다.

 

자식 프로세스의 종료코드는 자식 프로세스의 커널 오브젝트에 저장된다. 자식 프로세스가 종료될때 커널 오브젝트를 소멸시키면 문제가 발생할 수 있다.

 

GetExitCodeProcess 함수

GetExitCodeProcess 함수는 첫번째 인자로 전달된 핸들이 가리키는 프로세스가 반환하는 종료코드(Exit Code, 종료 상태를 알리는 값)을 얻기 위한 함수이다. 전달된 핸들의 프로세스가 종료되지 않고 실행중이라면, STILL_ACTIVE를 반환한다.

 

return에 의해 반환되는 값이나 exit 함수 호출시 전달되는 인자는 종료상황을 알리기 위해 사용된다. 일반적으로 종료코드 -1이나 0은 비정상적 종료를 알리고자 하는 경우에 많이 사용한다.

 

자식 프로세스의 종료코드는 자식 프로세스의 커널 오브젝트에 저장된다. 자식 프로세스가 종료될때 커널 오브젝트도 동시에 소멸된다면 부모 프로세스는 자식 프로세스의 종료코드를 얻을 수 없게 된다. 때문에 프로세스가 종료되었다고 해서 커널 오브젝트까지 동시에 소멸시키지는 않는다.

 

커널 오브젝트는 해당 커널 오브젝트를 참조하는 대상이 하나도 없을때 소멸시킨다.(windows 에서)

 

커널 오브젝트를 참조하는 프로세스가 하나라도 있을 시에는 커널 오브젝트는 소멸되지 않는다. Windows는 커널 오브젝트 소멸 시기를 결정하기 위해 UsageCount를 관리한다.

 

UsageCount는 커널 오브젝트에 접근가능한 대상의 수를 나타낸다.

프로세스는 생성과 동시에 커널오브젝트의 UsageCount가 1이된다. 그리고 자식 프로세스의 경우 UsageCount가 2가 된다. 왜냐하면 프로세스 본인과 부모 프로세스가 PROCESS_INFORMATION 구조체를 통해서 커널 오브젝트에 접근이 가능하기 때문이다.

 

프로세스는 GetCurrentProcess 함수 호출을 통해서 언제든 자신의 커널 오브젝트 참조를 위한 핸들을 얻을 수 있다. 그렇기 때문에 프로세스 생성시 Usage Count는 무조건 1 이상이다.

 

자식 프로세스가 종료 된 후 자식 커널 오브젝트

자식 프로세스가 종료되면 커널오브젝트에 접근하는 대상이 하나 줄기 때문에 Usage Count 값도 1 줄어든다.

 

CloseHandle 함수

CloseHandle 함수는 핸들을 반환하면서 커널 오브젝트의 Usage Count를 하나 감소시키는 기능을 지닌다.

프로세스의 경우 프로세스가 종료되는 시점에서도  UsageCount가 하나 감소한다.

 

CloseHandle 함수와 프로세스 종료는 별개이다. 프로세스 종료 요청시에 사용되는 함수는 TerminateProcess 이다. 이것은 강제 종료 요청함수이다.

 

바탕화면에 있는 아이콘을 더블 클릭해서 프로세스를 생성할 경우, 프로세스의 UsageCount는 2이다. 바탕화면도 일종의 프로세스이고 더블 클릭이라는 이벤트를 통해서 바탕화면 프로세스에게 프로세스 생성을 요청하는 것이기 때문이다.

728x90
728x90

커널 오브젝트의 종속 관계

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

커널 오브젝트는 프로세스에 종속적인 것이 아니라, 운영체제에 종속적인 관계로 커널 오브젝트의 소멸 시점은 운영체제에 의해서 결정된다. 커널 오브젝트는 프로세스에 종속적인 것이 아니라 운영체제에 종속적인 관계로 여러 프로세스에 의해 접근 가능하다.

 

커널 오브젝트는 운영체제에 종속적이지만 핸들(핸들 테이블)은 프로세스에 종속적이다.

 

프로세스가 생성된 후 정보를 저장하는 PROCESS_INFORMATION pi; 에서 pi.hProcess를 통해 프로세스의 핸들을 받아온다.

 

PROCESS_INFORMATION 정의

typedef struct _PROCESS_INFORMATION

{

    HANDLE hProcess;                  //프로세스 핸들

    HANDLE hThread;                   //쓰레드 핸들

    DWORD dwProcessId;             //프로세스의 ID

    DWORD dwThreadId;              //쓰레드 ID

}PROCESS_INFORMATION;

 

위 정보들을 통해 자식 프로세스의 핸들을 얻을 수 있다.

핸들을 얻는 방법은 커널 오브젝트의 종류와 상황에 따라서 다양하다. 커널 오브젝트는 프로세스에 종속적인 것이 아니라 운영체제에 종속적인 관계로 여러 프로세스에 의해서 접근이(공유가) 가능하다.

 

dwProcessId는 새로 생성되는 프로세스 ID 정보로 채워지게 된다. 프로세스 핸들은 프로세스 커널 오브젝트를 가리키기 위한 것이고, 프로세스 ID는 커널 오브젝트가 아니라 프로세스 자체를 구분짓기 위한 것이다. hThread와 dwThreadId도 각각 핸들과 쓰레드 Id를 가리키는 것이다.

 

커널 오브젝트와 Usage Count

커널 오브젝트를 생성한 주체가 커널 오브젝트를 소멸시킬 권한을 가지고 있다. CreateProcess 함수 호출이 커널 오브젝트의 생성 원인이기는 하나 프로세스 생성에 대한 요청이며, 이 과정에서 운영체제가 프로세스를 관리하고자 커널 오브젝트를 생성한다. 즉 커널 오브젝트 생성 주체는 운영체제이다.

 

커널 오브젝트를 생성한 것은 프로세스가 아니고 프로세스에 종속적이지도 않기 때문에 프로세스가 소멸된다고 해서 커널 오브젝트가 소멸된다고 말할 수 없다.

 

CloseHandle 함수

BOOL Close Handle(

     HANDLE hObject;

);

위 함수는 핸들을 닫는다. 핸들을 반환한다고도 표현한다.

 

ex)

A프로세스는 실행과정에서 B프로세스를 생성한다. 그리고 나서 B프로세스의 핸들을 이용해서 CloseHandle 함수를 호출한다. 이는 B프로세스에 대해서 더이상 내가 관여할 바 아니니, B프로세스 핸들을 반환하라 라는 의미이다.

CloseHandle 함수가 호출되는 시점에서 B프로세스가 종료된다면, CloseHandle 함수는 프로세스 종료 및 커널 오브젝트 반환 기능이 있다고 결론 내릴 수 있다.

 

커널 오브젝트 소멸 예시

위 그림은 CloseHandle함수에 의해서 B프로세스 및 해당 커널 오브젝트가 소멸된다는 가정하에 진행되는 그림이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

커널 : 컴퓨터를 운영하는데 있어서 중심이 되는 운영체제 핵심 부분

커널 오브젝트 : 커널에서 관리하는 중요한 정보를 담아둔 데이터 블록

 

프로세스를 생성하는 실질적인 주체는 운영체제이다. 프로그래머가 아니다. CreateProcess 함수호출을 통해 프로세스 생성을 요구한 것이고, Windows 운영체제가 우리의 요구에 맞게 프로세스를 생성해 주는 것이다. 그러므로 프로세스를 생성하는 실질적인 주체는 운영체제이다.

 

프로세스 생성과 소멸, 프로세스 상태변화 등 생성된 프로세스를 관리하는 것도 운영체제가 하는 일이다.

 

동시에 여러개의 프로세스를 관리하기 위해선 운영체제 입장에서 고정적으로 저장하고 갱신해야 할 정보들이 생기기 마련이다. 프로세스 상태정보(Running, Blocked, Ready 상태)와 우선순위 정보등의 정보는 운영체제 내부에 저장되어야 한다. 그리고 프로세스 상태정보와 프로세스 우선순위 정보도 변경될때 마다 갱신되어야 한다. 이러한 정보 저장과 갱신을 통한 정보들로 프로세스 스케줄러가 프로세스를 관리할 수 있다.

 

운영체제가 프로세스를 관리하기 위해 프로세스에 관련된 몇몇 정보를 저장할 수 있어야 하고, 참조 및 변경도 가능해야 한다. 이러한 프로세스 정보를 저장하기 위해 구조체를 정의하고, 이 구조체를 커널 오브젝트 라고 부른다. 커널 오브젝트는 프로세스가 생성될때 마다 하나씩 생성된다.

프로세스의 커널 오브젝트는 프로그래머가 직접 생성하거나 조작할 수 없다.

 

프로세스가 생성될 때에만 커널 오브젝트가 생성되는 것은 아니다. 프로세스 내에서 흐름을 구성하는 쓰레드를 생성할 때에도, IPC를 위해 사용되는 파이프나 메일 슬롯을 생성할 때에도 커널 오브젝트를 생성해서 필요한 정보들을 채워야만 한다.

 

프로세스, 쓰레드, 파이프, 메일 슬롯 등 커널 오브젝트를 생성할 때 커널 오브젝트의 종류에 따라서 서로 다른 구조체를 기반으로 생성된다. 대상에 따라 관리되어야할 정보들이 다르기 때문에 커널 오브젝트의 형태(커널 오브젝트를 구성하는 멤버)도 다를 수 밖에 없다.

 

예를 들어 파일이 생성될때 파일 커널 오브젝트에는 파일 속성(Read 모드, Write 모드 or Read/Write 모드)정보가 저장되어야 한다. Read 모드로 개방된 파일에 데이터를 저장하려는 경우, Windows에 의해 접근이 허용되지 않는다. 반면에 프로세스 커널 오브젝트에 파일 속성 정보를 저장할 필요가 없고 프로세스 우선 순위를 저장하기 위한 멤버가 필요하다.

 

커널 오브젝트 : 프로세스, 쓰레드 혹은 파일과 같은 리소스들을 관리하기 위해 필요한 정보를 저장하는 메모리 블록

 

☆Windows 커널에 의해서 관리되는 리소스 수만큼 커널 오브젝트도 생성된다.

 

Kernel Object                                              Resource

파이프 커널 오브젝트 <--------------------------> 파이프

프로세스 커널 오브젝트 <------------------------> 프로세스

쓰레드 커널 오브젝트 <----------------------------> 쓰레드

 

프로그래머는 직접 커널 오브젝트를 조작할 수 없다. 그러나 시스템 함수 호출을 통해 간접적인 조작은 가능하다.

 

프로세스 우선순위 변경

BOOL SetPriorityClass(

          HANDLE hProcess,

          DWORD dwPriorityClass

);

hProcess : 우선순위를 변경할 프로세스의 핸들(Handle)

dwPriorityClass : 새로 적용할 우선순위 정보

 

"hProcess가 가리키는 프로세스의 우선순위를 dwPriorityClass로 변경한다."

 

SetPriorityClass는 특정 프로세스의 우선순위를 높이는 일이다. 그러나 프로세스의 우선순위 정보는 프로세스 커널 오브젝트에 존재한다. windows는 커널 오브젝트를 생성할 때마다 핸들이라는 정수값을 부여한다. 이 정수값만 알 수 있다면, 커널 오브젝트를 지시하는것은 쉬워진다.

 

Handle                                           Kernel Object                                                Resource

파이프 핸들 <------------------------>파이프 커널 오브젝트 <-----------------------------> 파이프

프로세스 핸들<---------------------->프로세스 커널 오브젝트 <-------------------------->프로세스

쓰레드 핸들 <---------------------->쓰레드 커널 오브젝트 <------------------------------->쓰레드

 

SetPriorityClass 함수의 첫번쨰 인자는 프로세스의 커널 오브젝트를 가리키는 핸들을 전달하는 것이다.

 

*****Sleep함수는 프로세스를 Blocked상태가 되게 한다.******

 

현재 실행되고 있는 프로세스의 핸들 얻기

GetCurrentProcess함수는 현재 실행중인 프로세스(GetCurrentProcess 함수를 호출한 프로세스)의 핸들을 얻을 때 사용되는 함수이다. GetCurrentProcess 함수의 반환값을 통해 핸들을 얻게된다.

HANDLE GetCurrentProcess(VOID);

 

현재 실행중인 프로세스의 우선순위를 높이는 방법

SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

 

 

프로그램 실행중

출력 함수 호출이 완료되기도 전에, 함수가 호출되어 실행되는 중간에 CPU할당 시간을 다른 프로세스에게 넘겨 줄 수도 있다. CPU는 명령어 단위로 실행한다. 즉 출력함수의 명령어 수행중 다른 프로세스에게 CPU할당이 넘어갈 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

프로그램 실행중에 또하나의 프로세스를 생성할 수 있다.

 

Create Process 함수의 이해

프로세스 생성을 위해 Create Process 함수를 제공한다. 이때 Create Process 함수를 호출하는 프로세스를 부모 프로세스(Parent Process)라 하고, Create Process함수 호출에 의해 생성된 프로세스를 가리켜 자식 프로세스(Child Process)라고 한다. 만약에 자식 프로세스가 Create Process 함수 호출을 통해 자식 프로세스를 생성하면, 그 사이에서도 부모 자식 관계는 형성된다.

 

Create Process 선언

BOOL CreateProcess(

   LPSTR lpApplicationName,

   LPSTR lpCommandLine,

   LPSECURITY_ATTRIBUTES lpProcessAttributes,

   LPSECURITY_ATTRIBUTES lpThreadAttributes,

   BOOL bInheritHandles,

   DWORD dwCreationFlags,

   LPVOID lpEnvironment,

   LPCTSTR lpCurrentDirectory,

   LPSTARTUPINFO lpStartupInfo,

   LPPROCESS_INFORMATION lpProcess_Information

);

 

lpApplicationName : 생성할 프로세스의 실행 파일 이름을 인자로 전달한다. 경로명을 지정할 수 있고, 경로명을 지정하지 않을 경우 프로그램의 현재 디렉터리(Current Directory)에서 실행파일을 찾게된다.

 

lpCommandLine : 생성하는 프로세스에 인자를 전달할 때 이 두번째 매개변수를 사용한다. 첫번째 전달인자에 NULL을 전달하고, 두번째 전달인자에 실행파일의 이름을 전달할 수 있다. 이 경우 표준검색 경로를 기준으로 실행파일을 찾게된다.

 

lpProcessAttributes : 프로세스의 보안 속성을 지정할 때 사용하는 인자이다. 보통 NULL을 전달하고 디폴트 보안속성이 지정된다.

 

lpThreadAttributes : 쓰레드의 보안속성을 지정할 때 쓴다. NULL을 전달할 경우 디폴트 보안 속성이 지정된다.

 

hInheritHandle : 전달인자가 TRUE인 경우, 자식 프로세스는 부모 프로세스가 소유하는 핸들 중 일부(상속 가능한 핸들)를 상속한다.

 

dwCreationFlag : 생성하는 프로세스의 특성( ex)우선순위) 을 결정 지을때 사용되는 옵션이다.

 

lpEnvironment : 프로세스마다 EnvironmentBlock(환경 블록)이라는 메모리 블록을 관리한다. 이 블록을 통해서 프로세스가 실행에 필요로 하는 문자열을 지정할 수 있다.

 

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

 

lpStartupInfo : STARTUPINFO 구조체 변수를 초기화한 다음에 이 변수의 포인터를 전달한다. STARTUPINFO 구조체 변수는 생성하는 프로세스의 속성을 지정할 때 사용된다.

 

lpProcessInformation : 생성하는 프로세스 정보를 얻기위해 사용된다. PROCESS_INFORMATION 구조체 변수의 주소값을 인자로 전달한다. 전달된 주소값이 가리키는 변수에 프로세스 정보가 채워진다.

 

 

STARTUPINFO 구조체 선언

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;

 

현재 디렉터리의 설정

일반적으로 프로세스가 생성되면 프로세스의 현재 디렉터리는 프로세스의 실행파일이 존재하는 디렉터리로 생성된다.

 

프로세스의 현재 디렉터리의 위치확인

DWORD GetCurrentDirectory(

     DWORD nBufferLength;

     LPTSTR lpBuffer

);

 

두번째 전달인자 lpBuffer는 현재 디렉터리 정보가 저장된 메모리 버퍼의 포인터이고, 첫번째 전달인자 nBufferLength는 현재 디렉터리 정보가 저장될 메모리 버퍼의 크기로서, 저장 가능한 문자열 길이정보가 전달되어야 한다.

 

BOOL SetCurrentDirectory(

     LPCTSTR lpPathName

);

위 함수 호출 시 lpPathName 전달인자를 통해서 현재 디렉터리를 변경할 수 있다.

 

CreateProcess 함수 호출시 아래와 같은 형태는 불가능하다.

CreateProcess(

     NULL,

     _T("ABC.exe 10 20"),

   NULL,

}

CreateProcess 함수는 내부적으로 두번째 인자로 전달된 문자열에 변경을 가한다. 그렇기 때문에 두번째 전달인자는 문자열의 변수 형태여야 한다.

 

CreateProcess 함수의 첫번째 전달인자를 통해서 실행파일의 이름을 전달할 경우, 현재 디렉터리 기준으로 실행파일을 찾게 되지만, 두번째 전달인자를 통해서 실행파일이름을 전달할 경우 아래의 표준 검색경로 순서대로 실행파일을 찾는다.

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

2.실행중인 프로세스의 현재 디렉터리

3.Windows의 시스템 디렉터리

4.Windows 디렉터리

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

프로세스의 스케줄링(Scheduling)

CPU는 하나인데 여러개의 프로세스를 동시에 실행할 수 있다. 그 방법은 하나의 CPU가 여러개의 프로세스를 번갈아가면서 실행하는 것이다. 멀티 프로세스 운영체제에서 여러개의 프로세스가 실행되는 것처럼 보이는 이유는 여러개의 프로세스들이 CPU할당 시간을 나누기 때문이다.

 

스케줄링 기본원리

프로세스의 CPU할당 순서 및 방법을 결정짓는 일을 가리켜 스케줄링(Scheduling)이라 한다. 이때 사용되는 알고리즘을 스케줄링 알고리즘(Scheduling Algorithms)이라 한다. 스케줄링 알고리즘을 적용해서 실제로 프로세스를 관리하는 운영체제 요소(모듈)을 스케줄러(Scheduler)라고 한다.

 

멀티프로세스는 CPU를 바쁘게 한다.

A,B,C 프로세스를 모두 실행시킨 후 멀티 프로세스 운영체제의 스케줄러에 의해서 프로세스들이 관리하도록 한다. 정해진 순서에 의해서 CPU의 실행시간을 나눠서 할당받아 실행하는 형태이다.

 

프로그램은 실행되는 과정에서 많은 시간을 I/O(입력 및 출력)에 할당 한다. I/O는 데이터 입출력을 뜻한다. 파일 입출력 뿐만아니라 네트워크로 데이트럴 송수신 하는 것도 I/O에 해당한다. 입출력에 관련된 일을 할 경우 CPU는 아무일도 하지않고 대기하게 된다.

 

A프로세스가 I/O에 관련된 일을 할 경우, 운영체제는 스케줄러를 통해서 다른 프로세스가 실행되도록 스케줄링한다.

즉 A프로세스가 I/O작업을 하는 동안 B프로세스가 CPU에 의해서 실행을 시킬 수 있다.

 

프로세스의 상태 변화

여러개의 프로세스들이 돌아가면서 실행되기 때문에, 프로세스 상태는 시간 흐름에 따라 변화한다.

 

 

상황 1. S(Start)에서 Ready 상태로의 전이를 보여준다.

S는 프로세스가 생성됨을 의미한다. 프로세스는 생성과 동시에 Ready상태로 들어간다. Ready상태에 있는 프로세스는 CPU에 의해 실행되기를 희망하는 상태이다. 현재 CPU에 의해서 임의의 프로세스가 실행중일 수 있어 바로 Running상태가 되는것이 아니고 Ready상태가 된다.

 

상황 2. Ready 상태 -> Running

Ready상태에 있는 프로세스들은 스케줄러에 의해서 관리되는 프로세스들이다. 스케줄러는 Ready 상태에 있는 프로세스중 하나를 선택해서 CPU에 의해 실행될 수 있도록 한다.

Ready 상태에 있는 프로세스들 중 스케줄러에 의해 선택된 프로세스는 Running 상태가 되어 실행된다.

 

상황 3. Running 상태 -> Ready

일의 중요도에 따라 실행순서를 정하기 위해서 프로세스에는 우선순위라는 개념이 존재한다. 프로세스 생성시 중요도에 에 따라 우선순위가 높다면 A프로세스를 Ready상태로 변경하고 B프로세스를 Running 상태로 변경한다.

A프로세스 Running -> Ready

상황 4. Running 상태 -> Blocked 상태

일반적으로 데이터 입출력에 관련된 일을 하는 경우 프로세스가 실행을 멈추는 상태(Blocked)로 들어간다. 데이터 입출력을 진행 중인 프로세스는 잠시 내려오게 하고(Blocked) Ready상태에 있는 프로세스중 하나를 대신 실행시키는 것이다.

 

상황 5.Blocked 상태 -> Ready 상태

Ready상태는 스케줄러에 의해 선택되어 바로 Running이 가능한 상태이고 Blocked 상태는 스케줄러에 의해 선택될 수 없는 상태이다. 입출력이 완료된 Blocked 상태에 있는 프로세스는 다시 Ready 상태가 되어 스케줄러의 선택을 기다려야 한다.

 

컨텍스트 스위칭(Context Switching)

CPU내에 존재하는 레지스터들은 현재 실행 중에 있는 프로세스 관련 데이터들로 채워진다. 즉 실행중인 프로세스가 변경되면 CPU내에 레지스터들의 값이 변경된다. 컨텍스트 스위칭이란 하나의 프로세스를 실행하고 있는 상태에서 다음 우선 순위의 프로세스가 실행되어야 할 때 기존의 프로세스의 레지스터들을 메모리에 저장하고 메모리에 존재하는 다음 프로세스의 정보를 레지스터로 옮기는것이 컨텍스트 스위칭이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90

'Programming > Windows System Programming' 카테고리의 다른 글

커널 오브젝트에 대한 이해  (0) 2020.06.10
프로세스 생성  (0) 2020.06.08
프로세스의 이해  (0) 2020.06.07
Direct 모드와 Indirect 모드  (0) 2020.06.02
LOAD & STORE 명령어 디자인  (0) 2020.05.27
728x90

요즘 운영체제는 "멀티 프로세스(Multi-Process)운영체제" 라고 불린다. 이는 프로세스라는 것이 여러개 존재할 수 있는 운영체제라는 뜻이다.

 

프로세스란 실행중인 프로그램을 의미한다.

실행파일(.exe)이 더블클릭되면, 프로그램 실행을 위해 메모리(RAM) 할당이 이루어지고, 메모리 공간으로 바이너리 코드가 올라간다.

이순간부터 프로그램은 프로세스라고 불리게된다. 즉 실행중인 프로그램이 프로세스이다.

 

프로세스를 구성하는 요소

Execution of "C" Program

프로그램이 실행되면 각각 데이터가 특정 영역에 저장된다.

Data 영역 : 전역변수(global), 정적 변수(static), 배열(array), 구조체(structure) 등이 저장된다. 초기화 된 데이터는 data영역에 저장되고, 초기화되지 않는 데이터는 BSS(Block Stated Symbol)영역에 저장된다. BSS는 초기화되지 않은 전역 데이터를 위한 영역이다.

 

Stack 영역 : 지역 변수 할당과 함수 호출시 전달되는 인자값들의 저장을 위해 존재한다. LIFO(Last in First out)데이터 구조를 가진다.

 

Heap 영역 : 필요에 의해 동적으로 메모리를 할당할 때 사용. malloc, calloc 함수에 의해 할당된다.

 

Code 영역 : 프로그램을 실행시키면, 실행파일 내에 존재하는 명령어들이 메모리상에 올라가서 순차적으로 실행되는데 실행파일을 구성하는 명령어들이 올라가는 영역을 Code 영역이라고 한다.

 

프로그램 실행시 메모리 구조

가상메모리에 올라간 프로세스 메모리 구조

 

Register Set

실행파일을 실행하면 실행을 위한 데이터들로 레지스터가 채워진다.

즉 레지스터들의 상태까지도 프로세스의 일부라고 말할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

Direct 모드의 문제점과 Indirect모드의 제안

하나의 명령어에 여러 정보를 담다보니 표현하는 데이터 크기에 제한이 따른다는 문제점이 등장 하였다.

예를 들어 LOAD 명령어의 메인 메모리 주소값을 나타내는 source 부분에서 문제가 생길 수 있다.  이 부분에 총 여덟개의 비트 수가 할당되어 0x0000 ~ 0x00ff까지만 표현할 수 있다.

만약에 0x0100번지 값을 참조하고자 한다면 문제가 된다.

 

위에 설명한 메모리 접근 방법을 Direct모드라 한다.

이러한 Direct모드가 지니고 있는 단점을 해결하기 위해서 Indirect 모드가 등장했다.

Direct 모드는 주소를 직접적으로 표현하는데 반대로 Indirect 모드에서는 지정하는 주소에 저장된 값을 주소로 참조한다.

 

 

direct 모드 명령어

 

Indirect 모드 명령

Indirect 모드 명령어를 보면 피연선자 0x10을 [ ] 기호로 감싸고 있다. 이는 Indirect 모드로 메모리를 참조하는 명령어 구성을 위해서 정의해놓은 기호이다. 즉 [ ] 기호로 주소값을 감싸면 Indirect 모드 연산을 의미한다.

 

STORE 명령어 에서도 Indirect 모드는 동일하다.

 

 

 

 

int a= 10;    //0x0010 번지

int b= 20;    //0x0100 번지

int c = 0;    //0x0020 번지

c = a+b 

위 예제의 명령어는

 

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

이다.

 

 

728x90
728x90

LOAD & STORE 명령어의 필요성

명령어를 디자인 하는 과정에서 "연산결과를 레지스터에만 저장할 수 있도록 하겠다"는 제한 사항이 있다. 이것은 모든 피연산자에 메인메모리 주소값이 올 수 없다는 제약이다.

그렇기 때문에 지금까지 디자인한 명령어로 아래의 연산을 하지 못한다.

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

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

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

c = a+b;

 

변수 a,b,c는 메인메모리 0x10번지, 0x20번지, 0x30번지에 할당되었다.

"0x10번지에 저장된 값과 0x20번지에 저장된 값을 더해서 0x30번지에 저장하라" 라는 문제를 해결하기 위해서는

레지스터와 메인메모리 사이에서 데이터를 전송할 수 있는 명령어가 필요하다.

 

 

메인 메모리에 저장된 데이터를 레지스터로 이동시키는 명령어 LOAD, 레지스터에 저장된 데이터를 메인 메모리로 이동시키기 위한 명령어 STORE가 필요하다. 각각 명령어는 피연산자가 두개(메인 메모리 정보, 레지스터 정보)면 된다.

 

LOAD 명령어

 

16비트 LOAD 명령어 설계

destination : 데이터를 저장할 레지스터 정보

source : 데이터를 읽어올 메모리의 주소 정보

 

LOAD는 이진코드 110으로 정의했다.

 

ex) LOAD r3, 0x07

위 명령어는 "0x07번지에 존재하는 데이터를 레지스터 r3에 저장하라"이다.

명령어 구조는 아래와 같다.

 

STORE명령어

16비트 STORE 명령어 설계

source : 데이터를 읽어올 레지스터 정보

destination : 데이터를 저장할 메모리 주소 정보

 

STORE는 이진코드 111로 정의한다.

 

ex) STORE r2, 0x08

위 명령어는 "레지스터 r2에 존재하는 데이터를 메인 메모리 0x08번지에 저장하라"는 의미이다. 아래는 이진 명령어 이다.

 

예제 명령어 구성

int a = 10;         //0x10번지

int b = 20;         //0x20번지

int c = 0;          //0x30번지

c = a + b;

 

 

LOAD r1, 0x10

LOAD r2, 0x20

ADD r3, r1, r2

STORE r3, 0x30

 

피연산자가 레지스터가 되게끔 하기 위해 메모리에 저장된 값을 레지스터에 옮겨다 놓은 후 덧셈연산을 한다.

 

 

 

 

 

 

 

 

 

 

 

 

728x90

'Programming > Windows System Programming' 카테고리의 다른 글

프로세스의 이해  (0) 2020.06.07
Direct 모드와 Indirect 모드  (0) 2020.06.02
컴퓨터 구조의 접근방법  (0) 2020.05.25
64비트 기반 프로그래밍  (0) 2019.11.20
MBCS WBCS(유니코드) 동시지원  (0) 2019.08.11

+ Recent posts