Process Model
프로세스 구조
* Process
- 실행중에 있는, 메인 메모리에 Load되어 있는 프로그램이다.
- 프로그램은 일련의 명령어로 구성된 파일이다.
- 각 프로세스들은 독립적인 주소공간(Virtual Address)이 할당되어 각자의 Code를 처리한다.
- Kernel 프로세스*를 제외한 모든 프로세스는 Parent 프로세스에 의한 fork()로 생성된다.
(fork() 호출 이외의 방법은 없다.)
- Kernel은 exec() System Call을 통해 프로그램을 메인 메모리에 Load하고,
IP(Instruction Pointer)를 해당 프로그램의 시작 주솟값으로 설정하여 프로세스를 시작한다.
(즉, exec() 계열 함수가 Loader의 역할을 하는 것이다.)
* Kernel Process (Adam Process)
- Parent가 없는, 태초의 프로세스이다.
- UNIX/Linux에서는 init 혹은 systemd로 명명되어 있다.
* Program Flow (C Language)
Main Memory Structure (메인 메모리 구조)
- 메인 메모리는 크게 Kernel Memory Space, User Memory Space 로 구분된다.
- 프로그램에서는 자신의 메인 메모리 영역을 Byte 단위로 접근한다.
- Kernel은 전체 메인 메모리를 관리의 편의를 위해 Page 단위로 접근한다.
(메인 메모리 전체를 Byte 단위로 접근하면 그 크기가 너무 커지기 때문이다.)
1) Kernel Memory Space
- Non-Volatile Memory(Flash 등)에 적재되어 있던 Boot Loader는 OS Loader가 위치한 Storage 주소를 갖고 있는데,
시스템이 Power-On되면 이 Boot Loader에 의해 OS Loader가 메인 메모리에 Load되어 시스템 부팅이 시작된다.
- Boot Loader의 마지막 Instruction은 PC값을 OS Loader의 첫 Instruction으로 설정하는 명령이다.
- 메인 메모리에 Load된 OS Loader는 Storage에 저장되어 있던, 실행 가능한 Kernel Image를 메인 메모리에 Load한다.
- OS Loader의 마지막 Instruction은 PC값을 OS의 첫 Instruction으로 설정하는 명령이다.
(OS의 첫 부분은 init 프로그램 혹은 systemd 프로그램이다.)
- OS가 동작하기 시작하고, fork()를 통해 생성된 User Process(일반적으로 Daemon Process)들은
Kernel에 의해 메모리에 Load되고, 관리된다.
2) User Memory Space
- User Memory Space는 다시, Data Segment, Stack Segment, Code Segment로 구분된다.
- CPU Register에는 각각의 Segment의 시작위치와 종료위치가 저장되어 있기 때문에,
위 그림과 달리, 메인 메모리내에서 인접해있다는 보장이 없다.
- 컴파일러는 3개의 Segment를 각각 컴파일한다.
a) Data Segment
- Global Variable이나 Constant들이 저장되는 영역이다.
b) Stack Segment
- Local Variable들이 저장되는 영역이다.
* Heap
- Runtime 도중에 Dynamic하게 할당되는 메모리 영역이다.
c) Code Segment (Text, Instructions)
- High-Level 언어가 컴파일되어 만들어진 Assembly Instruction들이 저장되는 영역이다.
ex) Page의 단위가 1KB이고, 컴파일된 Code의 크기가 1.4KB라면, Code Segment에는 2개의 Page(2KB)만큼 할당될 것이다.
Reference: UNIX Network Programming Volume 1, 3E: The Sockets Networking API (W. Richard Stevens, Bill Fenner, Andrew M. Rudoff 저, Addison-Wesley, 2004)