이번 포스팅부터는 물리적인 메모리를 어떻게 관리할 것인가에 대해 살펴보겠습니다.
물리적 메모리는 일반적으로 두 영역으로 나뉘어 사용됩니다.
낮은 주소 영역에는 운영체제 커널이 항상 상주해있고, 높은 주소 영역에는 사용자 프로그램이 있습니다.
사용자 프로그램이 올라간 영역을 관리하는 방법은 크게 두 가지로 나누어 볼 수 있습니다.
첫 번째는 연속 할당(Contiguous allocation)으로 프로그램이 메모리에 올라갈 때 통째로 메모리에 올라가는 방식입니다. 즉 각각의 프로세스가 메모리의 연속적인 공간에 적재되는 것입니다.
두 번째는 불연속 할당(Noncontiguous allocation)으로 프로그램을 구성하는 주소 공간을 같은 크기의 페이지 단위로 쪼개서 페이지 단위로 메모리에 올리는 방식입니다.하나의 프로세스가 메모리의 여러 영역에 분산되어 올라갈 수 있습니다. 현대의 OS에서 사용하는 방식입니다.
이번 포스팅에서는 연속 할당에 대해 살펴보겠습니다.
1. 연속 할당(Contiguous allocation)
연속 할당도 두 가지로 나누어 볼 수 있습니다. 고정 분할 방식과 가변 분할 방식입니다.
(1) 고정 분할 방식 (Fixed Partition)
고정 분할 방식은 사용자 프로그램이 들어갈 물리적 메모리를 미리 분할해놓는 것입니다.
위 그림에서 프로그램 A는 분할 1에, 프로그램 B는 분할 3에 들어갈 수 있습니다. 하지만 프로그램 B는 분할 2에 들어가기엔 크기가 커서 분할 2에는 들어가지 못합니다. 이런 경우에 낭비되는 메모리 조각이 생기고, 이 조각은 외부 조각(External fragmentation)과 내부 조각(Internal fragmentation)으로 나누어 설명할 수 있습니다.
외부 조각은 올리려는 프로그램보다 분할된 메모리 조각의 크기가 작아(메모리 조각<프로그램) 사용이 되지 않는 것입니다. 크기가 작아 프로그램이 올라갈 수 없습니다.
내부 조각은 분할된 메모리 조각보다 프로그램의 크기가 작아(메모리 조각>프로그램) 사용되지 않는 공간입니다. 하나의 분할 내부에서 사용되지 않는 메모리 조각입니다. 즉 분할이 특정 프로그램에 배정되었지만 그 중에서 사용되지 않는 공간을 말합니다.
(2) 가변 분할 방식 (Variable Partition)
가변 분할 방식은 프로그램이 실행될 때마다 메모리에 올려놓는 방법입니다. 프로그램 A, B, C가 실행되고 프로그램 B가 끝나면 D가 실행된다고 가정해보겠습니다. 프로그램 실행 순서대로 메모리에 차곡차곡 쌓이다가 프로그램 B가 종료되면 D가 실행이 되어 메모리에 올라가야합니다. 하지만 프로그램 B 크기 보다 프로그램 D 크기가 더 크기 때문에 그 공간에 들어가지 못하는 문제가 생깁니다. 그래서 프로그램 B가 있던 자리는 빈 공간이 되고, 프로그램 D는 프로그램 C 밑에 할당됩니다.
Dynamic Storage-Allocation Problem
가변 분할 방식을 사용하면 프로그램이 실행되다가 종료될 때에 Hole이 생깁니다(사진의 파란색). Hole은 가용 메모리 공간, 비어있는 메모리 공간을 의미합니다. 다양한 크기의 hole들이 메모리 여러 곳에 흩어져 있기 때문에, 운영체제는 물리적인 메모리에서 할당 공간과 가용 공간을 관리해야 합니다.
그래서 hole 중에 어떤 hole에 프로그램을 집어넣을 것인지 결정해야합니다. 그 문제를 Dynamic Storage-Allocation Problem이라고 합니다. 다시 말해, 실행하려는 프로그램의 크기가 N인데 size N인 요청을 만족하는 적절한 hole을 찾는 문제입니다. 세 가지 정도의 방법이 있습니다.
1. First-fit
Hole 중에서 가장 처음 발견되는 hole에 할당하는 것입니다.
2. Best-fit
Size가 n 이상인 가장 작은 hole을 찾아 할당하는 것입니다. Hole들의 리스트가 크기 순으로 정렬되지 않은 경우 모든 hole의 리스트를 탐색해야합니다.
3. Worst-fit
가장 큰 hole에 할당하는 것입니다. Best-fit과 같이 모든 hole을 탐색해야합니다. 매우 비효율적인 방법입니다.
First-fit과 Best-fit이 Worst-fit보다 속도와 공간 이용률 측면에서 효과적이라는 실험 결과가 있습니다.
Compaction
위에서 언급한 방법 외에도, compaction은 작은 hole들을 한 곳으로 몰아 넣는 방법입니다. 외부 조각으로부터 생기는 hole들을 한 군데로 모아 아주 큰 홀을 만들면 Hole의 크기가 작아 사용하지 못했던 문제를 해결할 수 있습니다. 실행 중인 프로그램의 메모리를 한 군데로 모으는 작업이기 때문에 매우 비용이 많이 드는 방법입니다. 실행 중에도 메모리를 옮길 수 있는 Run time binding이 지원되어야 Compaction을 할 수 있고 프로세스의 주소가 실행 시간에 동적으로 재배치 가능한 경우에만 수행될 수 있습니다.
여기까지 연속 할당에 대해 알아보았습니다. 다음 포스팅에서는 불연속 할당에 대해 살펴보겠습니다.
참고자료
[KOCW 이화여대 반효경 교수님 - Memory Management 1]
https://core.ewha.ac.kr/publicview/C0101020140425151219100144?vmode=f
[ Operating System Concepts - Abraham Silberschatz ]
https://www.yes24.com/Product/Goods/89496122