운영체제 핵심 관리 대상인 메모리(주 기억 장치)에 대해 알아보자.
메모리 관리를 알기 위한 사전 지식부터 알아보자.

- 단위관련 용어 정의
- block
- 보조기억장치와 주기억장치 사이의 데이터 전송 단위
- size : 1 ~ 4kb
- word
- 캐시와 레지스터 사이의 데이터 전송 단위
- size : 16 ~ 64 bits
- (컴퓨터 cpu가 16 bits, 64 bits라고 표현하는 것이 여기서 착안)

Address Binding
- 프로그램의 논리 주소를 실제 메모리의 물리 주소로 매핑하는 작업 (소스코드와 메모리 주소 일치)
ex) int a 라고 정의 했을 때 메모리 주소 100번에 할당된 것을 일치시키는 작업
- binding 시점에 따른 구분 (언제 매핑하느냐)
- compile time binding
- 프로세스가 메모리에 적재될 위치를 컴파일러가 아는 경우.
- 위치 변하지 않음. (100번에 위치되면 항상 100번이어야 함)
- 프로그램 전체가 메모리에 올라가야 함.
- load time binding
- 메모리 적재 위치를 컴파일 시점에 모르면 대체 가능한 상대 주소 생성.
- 적재 시점(load time)에 시작 주소를 반영하여 사용자 코드 상의 주소를 재설정.
- 프로그램 전체가 메모리에 올라가야 함.
- run time binding
- address binding을 수행시간까지 연기.
- 프로세스가 수행 도중 다른 메모리 위치로 이동할 수 있음.
- HW 도움 필요. (MMU; memory management unit)
- 대부분의 OS가 사용.


Dynamic loading
- 모든 루틴(ex 함수)을 교체 가능한 형태로 디스크에 저장.
ex) 함수 a, b, c를 따로 저장했다 호출 시점에 메모리에 올림.
- 메인 프로그램만 메모리에 적재하여 수행.
- 루틴의 호출 시점에 address binding 수행.
- 실제 호출 전까지는 루틴에 적재하지 않음.
- 메모리 공간을 효율적으로 사용할 수 있음.
Swapping

- 프로세서 할당이 끝나고 수행 완료된 프로세스는 swap-device로 보냄 (swap-out).
- 새롭게 시작하는 프로세스는 메모리에 적재 (swap-in).
어떻게 메모리를 프로세스에 할당할까?
목차
Memory Allocation
continuous memory allocation
- 프로세스를 하나의 연속된 메모리 공간에 할당하는 정책 (프로그램 전체가 한 번에 올라감)
- 이럴 때 신경써야 하는 메모리 구성이 있음.
- 동시에 메모리에 올라갈 수 있는 프로세스 수 (프로그램에 몇 개를 올릴 수 있을까?)
- 각 프로세스에게 할당되는 메모리 공간 크기 (프로세스가 요구하는 크기만큼 줄 수 있는가?)
- 메모리 분할 방법 (어떻게 메모리를 자를까?)
uni-programming

- 하나의 프로세스만 메모리 상에 존재
- 가장 간단한 메모리 관리 기법
- 근데
프로그램 크기 > 메모리 크기
라면 문제가 발생함.
- 해결법
- overlay structure
- 메모리에 현재 필요한 영역만 적재.
- 사용자(개발자)가 프로그램의 흐름 및 자료구조를 모두 알고 있어야 함.
- 또 한가지 커널을 보호해야 함. 커널을 건드리면 프로그램이 죽을 수 있음.

- 해결법
- boundary address 사용.
- 메모리와 커널 사이 경계가 되는 주소를 적어 넘어오는 것을 방지함.
- 하지만 uni-programming은 근본적으로 다음과 같은 문제를 가짐.
- low system resource utilization : 시스템 활용도가 낮음.
- low system performance : 퍼포먼스가 낮음.
- 결국 하나만 올라가는 것이 원인임.
- 해결법 → 여러 개를 올릴 수 있는 multi-programming.
multi-programming
- 멀티 프로그래밍에서 메모리를 할당하는 방법은 2가지임.
- Fixed partition
- 메모리 공간을 고정된 크기로 분할.
- 미리 분할해 놓음.
- 각 프로세스는 하나의 partition(분할)에 적재되는 구조.
- 마찬가지로 boundary address를 사용해 커널을 보호함. 뿐만 아니라 파티션 사이에도 영역 침범하는 것을 막기위해 boundary register를 사용함.
- 여기서 등장하는 중요한 개념 ⭐
- Fragmentation (단편화)
- 단편화가 발생함에 따라 메모리가 낭비되는 것을 볼 수 있음. 단편화는 2가지 종류로 나뉨.
- internal fragmentation : partition 크기 > process 크기
- external fragmentation : 남은 메모리 크기 > process 크기 (연속된 공간 x)
- variable partition
- 유동적으로 변화하면서 단편화 문제를 해결함.
- 초기에는 전체가 하나의 영역이었다 프로세스를 처리하는 과정에서 메모리 공간이 동적으로 분할함. → internal fragmentation 해결
- 그럼 들어갈 공간이 많을 경우 어디다 넣어줄 것인지 고민하는 배치 전략이 필요함.
- First-fit (최초적합)
- 충분한 크기를 가진 첫 번째 partition 선택.
- simple, low overhead.
- 공간 활용률이 떨어질 수 있음.
- Best-fit (최적적합)
- 프로세스가 들어갈 수 있는 partition 중 가장 작은 곳 선택.
- 탐색 시간이 오래걸림 (overhead)
- 크기가 큰 partition을 유지할 수 있다는 장점이 있지만 작은 크기의 partition이 많이 발생한다는 단점이 있음.
- Worst-fit (최악적합)
- 프로세스가 들어갈 수 있는 partition 중 가장 큰 곳 선택.
- 탐색 시간이 오래걸림.
- 작은 크기의 partition 발생을 줄일 수 있지만 큰 크기의 partition을 확보하기 어려움.
- Next-fit (순차최초적합)
- 마지막으로 탐색한 위치부터 탐색. 최초 적합 전략과 유사.
- 메모리 영역의 사용 빈도 균등화.
- low overhead.
- 가장 좋다할 건 없고 시스템, OS에 따라 선택하는 것임.
- 그렇다면 external fragmentation 이슈는 어떻게 해결할까?
- Coalescing holes (공간 통합)
- 인접한 빈 영역을 하나의 partition으로 통합.
- low overhead.
- Storage compaction (메모리 압축)
- 모든 빈 공간을 하나로 통합.
- high overhead.
- 그래서 자주하지 않고, 일정시간 요청이 있을 때 실행.



