프로그램이 실제로 실행되기 위해서는 프로세스로 변환되어야 하는데, 이는 프로그램이 단순히 저장 장치에 저장된 코드와 데이터의 정적인 형태에서 벗어나, 운영 체제가 관리할 수 있는 동적인 실행 단위로 활성화되어야 하기 때문이다. 이 과정을 자세히 살펴보면 다음과 같다.
[프로그램 vs 프로세스]
- 프로그램(Program): 디스크와 같은 저장 매체에 저장된 실행 가능한 파일로, 코드와 데이터의 정적인 형태를 가지며, 실행되지 않는 상태이다.
- 프로세스(Process): 실행 중인 프로그램으로, 운영 체제가 메모리에 할당하고 실행을 관리하는 동적인 상태이다. 프로세스는 메모리, 실행 상태, 프로세스 ID 등 실행에 필요한 여러 자원과 정보를 포함한다.
[프로세스 생성 과정]
1. 프로그램의 로딩
컴파일 → 어셈블 → 링크 → 로드 순으로 작동한다.
- 컴파일은 고급 프로그래밍 언어로 작성된 소스 코드를 기계가 이해할 수 있는 저급 언어나 중간 언어(예: 바이트 코드)로 변환하는 과정이다. 이는 컴파일러라는 특수 소프트웨어에 의해 수행되며, 구문 오류나 타입 체크 등 초기 오류를 발견하는 단계도 포함된다.
- 어셈블은 어셈블리 언어로 작성된 코드를 기계어 코드로 변환하는 과정이다. 이 단계는 어셈블러라고 하는 도구를 사용하여 수행되며, 어셈블리 코드의 명령어를 기계가 실행할 수 있는 이진 명령어 형식으로 바꾼다.
- 링크는 하나 이상의 오브젝트 파일(컴파일 또는 어셈블 단계에서 생성된 파일)을 결합하여 단일 실행 파일을 생성하는 과정이다. 이 과정에서 외부 라이브러리 호출이나 다른 모듈 간의 참조를 해결한다. 링커는 필요한 코드와 라이브러리를 모아 최종적으로 실행 가능한 프로그램을 만든다. link에는 두 종류가 있다. Static Binding은 프로그램 실행 전 메모리 할당을 끝내는 것이다. 즉, 실행 파일에 필요한 라이브러리를 모두 통합해 넣기에 크기가 커진다. Dynamic Binding은 link 과정에서 라이브러리를 넣을 빈자리를 만들어 놓고 프로그램 실행 중 메모리 공간에 할당하는 방식이다. 보다 유연하게 공간을 사용할 수 있지만, 런타임 시간이 길어질 수 있다는 단점이 있다.
- 로드는 프로그램을 디스크에서 메모리로 전송하는 과정이다. 운영 체제는 프로그램의 실행 파일을 메모리의 적절한 위치에 코드와 데이터를 배치하여 프로세스를 생성하고, 실행을 시작할 수 있도록 준비한다. 로드 과정은 프로그램이 사용자 또는 시스템 요청에 의해 실행될 때 발생한다.
2. 메모리 할당(Allocation)
프로세스는 main memory에서 text, data, stack, heap영역 등을 포함한 메모리 공간을 할당받는다. text에는 프로그램의 실행 코드, data에는 상수(초기화된 전역 변수), heap에는 new/malloc을 통한 동적 할당 데이터, stack에는 함수 호출과 지역 변수가 포함된다.
Allocation 방법에도 두가지가 있다. 첫째, Static Memory Allocation은 실행 전에 미리 메모리 할당을 해놓는 방식으로 실행 중에 메모리 공간을 추가로 사용하지 못한다. Dynamic Memory Allocation은 프로그램 실행 중 메모리 할당이 가능한 방법으로, 필요없을 때 해제할 수도 있다.
Dynamic Allocation에서 메모리를 해제할 시 특정 영역이 비어 hole이 생긴다. 이러한 hole을 추적하여 free list를 만든 후, 메모리 할당이 필요한 프로세스가 있으면 해당 공간들을 할당해주어야 한다. free list를 관리하는 기법으로는 두가지가 있다. best fit과 first fit이 있다. best fit은 프로세스 실행을 위해 필요한 가장 최적 메모리 크기만큼 공간을 할당하는 방법이다. first fit은 프로세스 실행을 위해 필요한 처음 발견한 메모리 크기 이상의 공간을 할당하는 방법이다. first fit은 리스트 전체를 검색하는 것이 아니므로, 필요한 cost가 낮다. 하지만, 작은 빈 공간들이 많이 남아 fragmentation 발생할 수 있다. best fit은 반대로, 리스트 전체를 검색해야 하기에 cost가 높지만, 작은 빈 공간이 적게 남아 fragmentation이 적게 발생한다.
메모리 Relocation은 주로 두 가지 방법, 즉 정적 relocation과 동적 relocation으로 구분된다. 각 방법은 프로그램의 메모리 주소를 다루는 시점과 방식에서 차이를 보인다.
- 정적 relocation은 프로그램이 실행되기 전에 주소 변환을 수행하는 방식이다. 이 방법은 실행 파일이 메모리에 로드될 때 모든 메모리 주소를 물리적 주소로 변환한다. 변환된 주소는 프로그램 실행 동안 변경되지 않으며, 프로그램의 위치는 메모리 내에서 고정된다. 이 방식의 장점은 추가적인 하드웨어 구현이 필요 없다는 것이지만, 실행 중 메모리 크기 변경이 불가능하고, 프로그램의 주소 이동이 불가능하며, 다른 프로세스의 메모리 공간을 손상시킬 위험이 있다는 단점이 있다.
- 동적 relocation은 프로세스가 실행 중인 동안에도 주소 변환이 가능하도록 한다. 이 방식은 프로세스 실행 중 메모리 주소의 실시간 조정을 허용하여, 다양한 프로세스 간 메모리 공간을 보다 효율적으로 관리할 수 있다. 프로세스는 실행 중에도 메모리 위치를 변경할 수 있으며, 이는 특히 다중 작업 환경에서 유용하다. 단점은 메모리 할당 과정이 복잡하고 페이지 및 페이지 테이블에 각각 접근해야 하기 때문에 메모리 접근이 이중으로 발생할 수 있다는 것이다. 이는 TLB를 통해 개선될 수 있다. 이 방식은 투명성, 안전성, 효율성을 만족시키며, 실행 중에도 가상 주소를 물리 주소로 변환하는 과정이 필요하다. 이 변환 과정은 메모리 관리 유닛(MMU)에 의해 수행된다.
MMU: Memory Management Unit
MMU는 CPU가 사용하는 논리적 주소를 물리적 주소로 변환하는 장치이다. CPU는 논리적 주소를 통해 메모리 접근을 시도하며, MMU를 거쳐 실제 RAM이 관리하는 물리적 주소에 접근하게 된다. 이 과정을 통해 메모리 접근은 투명하게 관리되며, 시스템의 보안과 효율성을 높일 수 있다.
📌 base register: 프로세스의 가장 낮은 Virtual Address를 저장하는 레지스터로, virtural address를 번역하는 역할을 한다.
📌 limit register: 프로세스의 가장 높은 Virtual Address를 저장한는 레지스터로, 프로세스가 접근 가능한 Virtual Address Space의 최대 한계를 설정하여 타 영역에 들어가지 못하도록하여 보완성을 높인다.
3. 실행 상태 설정
프로세스 상태(Process State)는 프로세스의 생명 주기 동안 여러 단계를 거치며, 각 단계는 프로세스가 시스템 내에서 차지하는 역할과 상태를 나타낸다. 운영 체제의 스케줄러는 이러한 상태를 관리하고 CPU의 실행 시간을 조정하여 시스템의 자원을 효율적으로 활용한다.
프로세스의 상태
- 생성 (New): 프로세스가 생성되고 초기화되는 단계로, 시스템에 필요한 자원을 할당받기 위해 준비된다.
- 준비 (Ready): 프로세스가 CPU를 기다리는 상태로, 실행을 위해 필요한 모든 조건을 충족하고 실행을 기다린다.
- 실행 (Running): 프로세스가 CPU를 할당받아 명령어를 실행하는 상태이다.
- 대기 (Blocked): 프로세스가 특정 이벤트나 시간의 경과, 입출력 작업 완료 등을 기다리는 동안 CPU를 다른 프로세스에 양보하고 대기 상태가 된다.
- 종료 (Exit): 프로세스가 실행을 완료하고 시스템에서 제거되는 상태로, 관련 자원이 회수되고 프로세스 제어 블록(PCB)이 해제된다.
Process Control Block (PCB)
각 프로세스의 상태는 커널 메모리 영역에 존재하는 프로세스 제어 블록(PCB)에 저장된다. PCB는 프로세스의 모든 중요 정보를 담고 있어, context switch로 프로세스가 중단된 후 다시 실행될 때 이전에 중단된 지점부터 실행을 계속할 수 있도록 한다. PCB에는 다음과 같은 정보가 포함된다.
- 프로세스 식별자 (PID)
- 프로세스 상태
- 프로그램 카운터(PC) -> 다음 실행할 명령어 가르킴
- CPU 레지스터
- CPU 스케줄링 정보
- 메모리 관리 정보
- 계정 정보 및 입출력 상태 정보
이러한 정보는 프로세스가 시스템 리소스를 효과적으로 사용하고, 운영 체제가 여러 프로세스를 관리할 수 있게 도와준다. PCB는 프로세스가 시스템에서 자원을 효율적으로 공유하고, 복잡한 작업을 관리하는 데 필수적인 역할을 수행한다.
*context swithing: ****PCB에 실행 중인 프로세스의 모든 상태를 저장하고, Scheduling된 프로세스 상태를 복원하고 실행되는 과정으로, PCB에 저장하는 등의 추가 작업으로 인한 자원&시간 소비를 유발한다.
Scheduling Queue
프로세스가 시작되고 초기화가 완료되면, 프로세스는 먼저 ready queue에 진입하여 cpu core을 점유할 때까지 기다린다. 또한, 어떤 특정 이벤트가 발생하기를 기다리는 프로세스의 경우, waiting queue에 위치시키고 기다리게 한다. 이러한 queue들은 PCB의 Linked List로 구현할 수 있다.
'CS > 운영체제' 카테고리의 다른 글
[OS] File System (0) | 2024.07.01 |
---|---|
[OS] Memory Management (0) | 2024.07.01 |
[OS] Deadlock (0) | 2024.07.01 |
[OS] CPU Scheduling (0) | 2024.07.01 |
[OS] Synchronization (0) | 2024.07.01 |