메모리 관리 작업 (Memory Management)
폰 노이만 구조에 따르면 프로그램은 메인 메모리에 올라와야 실행된다. 이때 메모리 관리 시스템(Memory Management System)은 여러 작업을 동시에 처리할 때 메모리를 관리하는 역할을 담당한다.
메모리 관리 작업은 크게 "가져오기", "배치", "재배치"로 구분된다.
- 가져오기(Fetch): 실행할 프로세스와 데이터를 메모리로 가져오는 작업
- 배치(Placement): 가져온 프로세스와 데이터를 메모리의 어떤 부분에 올려놓을지 결정하는 작업, 배치 작업 전 메모리를 어떤 크기로 분할할지 결정하는 것이 매우 중요하다. 이때, 메모리를 같은 크기로 자르는 것을 페이징(Paging), 프로세스의 크기에 맞게 자르는 것을 세그먼테이션(Segmentation)이라고 한다.
- 재배치(Replacement): 새로운 프로세스를 가져오기 위하여 오래된 프로세스를 내보내는 작업, 앞으로 사용하지 않을 프로세스를 찾아 내보내야 시스템의 성능이 올라간다. 이에 대한 알고리즘을 교체 알고리즘(Replacement Algorithm)이라고 한다.
메모리 주소 (Memory Address)
논리 주소와 물리 주소
각 메모리에는 주소 공간이 있다. 하드웨어의 입장에서 바라본 주소 공간을 "물리 주소 공간(Physical Address Space)", 사용자의 입장에서 바라본 주소 공간을 "논리 주소 공간(Logical Address Space)"라고 한다.
예를 들어, 물리 메모리의 360번지부터 프로세스가 사용할 때, 40번지는 물리 메모리의 주소 400번지가 된다. 이것이 물리 주소이다. 메모리 주소 레지스터가 사용하는 주소이며 컴퓨터에 꽂힌 램 메모리의 실제 주소이다. 40번지는 논리 주소이며 시작점을 0으로 놓았을 때 40번지에 위치하는 주소를 말한다.
물리 주소 공간은 0번지부터 시작하고 최대 주소 크기는 컴퓨터에 설치된 메모리의 크기에 따라 달라진다. 반면, 논리 주소 공간도 0번지부터 시작하지만 컴퓨터가 허용하는 최대의 주소 크기를 가진다.
논리 주소로 이루어진 프로세스를 실행하면 이를 물리 주소로 변환하는 작업이 필요한데 이는 "메모리 관리 유닛(Memory Management Unit)"이 담당하게 된다. 메모리 관리 유닛은 다음의 절차를 따라 실행된다. (아래의 예시는 물리 메모리의 360번지부터 프로세스가 사용한다고 가정한다.)
- 사용자 프로세스가 논리 주소 40번지에 있는 데이터를 요청한다.
- CPU는 메모리 관리 유닛에 40번지에 있는 내용을 가져오라고 명령한다.
- 메모리 관리 유닛은 재배치 레지스터를 사용하여 메모리 400번지에 저장된 데이터를 가져온다.
단일 프로그래밍의 메모리 할당
메모리 오버레이 (Memory Overlay)
실제 메모리보다 큰 프로그램이 있다면 전체 프로그램을 메모리에 가져오지 않고 적당한 크기로 프로그램을 잘라서 가져오면 작은 메모리로 큰 프로그램을 작동시킬 수 있다. 이를 "메모리 오버레이(Memory Overlay)"라고 한다. 프로그램을 몇 개의 모듈로 나누고 필요할 때마다 모듈을 메모리에서 가져와 사용한다.
메모리 오버레이에서 어떤 모듈을 가져오거나 내보낼지는 프로그램 카운터(PC:Program Counter)가 결정한다. 메모리 오버레이 가지는 중요한 의의는 다음과 같다.
- 한정된 메모리에서 메모리보다 더 큰 프로그램을 실행할 수 있다.
- 프로그램 전체가 아니라 일부만 메모리에 올라와도 실행할 수 있다.
스왑 (Swap)
메모리가 모자라서 쫒겨난 프로세스를 저장장치의 특별한 공간에 모아두는데 이 영역을 "스왑 영역(Swap Area)"이라고 한다. 스왑 영역에서 메모리로 데이터를 가져오는 것을 스왑인(Swap In), 메모리에서 스왑 영역으로 데이터를 내보내는 것을 스왑아웃(Swap Out)이라고 한다.
저장장치는 본래 저장장치가 관리하지만, 스왑 영역은 쫓겨났다가 다시 돌아가는 데이터가 머무는 곳이기에 스왑 영역은 메모리 관리자가 관리한다. 메모리 오버레이를 통해 메모리보다 큰 프로그램을 실행할 때는 프로그램을 메모리보다 작은 크기의 모듈로 나누어 사용하게 되는데, 거기에 스왑까지 이용하게 되면 스왑 영역의 크기가 메모리의 크기로 인식되어 사용자는 실제 메모리와 스왑 영역의 크기를 합친 것을 전체 메모리의 크기로 인식하게 된다.
다중 프로그래밍의 메모리 할당
한 번에 한 프로세스만 실행되는 단일 프로그래밍 환경에서의 메모리 관리 문제보다 한 번에 여러 프로세스를 동시에 실행하는 다중 프로그래밍 환경에서의 메모리 관리 문제는 훨씬 더 복잡하다. 프로세스들의 크기가 다르기에 메모리를 어떻게 나누어 사용할지를 결정해야 하기 때문이다.
메모리를 어떤 크기로 나눌 것인지 결정하는 방법으로는 크게 "가변 분할 방식"과 "고정 분할 방식"이 있다.
- 가변 분할 방식(Variable-Size Partitioning): 프로세스의 크기에 따라 메모리를 나눈다.
- 고정 분할 방식(Fixed-Size Partitioning): 프로세스의 크기와 상관없이 메모리를 같은 크기로 나눈다.
가변 분할 방식
가변 분할 방식은 프로세스의 크기에 맞춰 메모리를 할당하는 방식으로 "세그먼테이션 메모리 관리 기법(Segmentation)"이라고 한다. 물리 메모리에서는 하나의 프로세스에 해당하는 주소 공간이 연속적으로 이어지기 때문에 가변 분할 방식에서 한 프로세스는 메모리의 연속된 공간에 배치된다.
가변 분할 방식은 프로세스를 한 덩어리로 처리하여 하나의 프로세스를 연속된 공간에 배치할 수 있다. 다만, 메모리 관리가 복잡하다. 프로세스들이 올라와 작업하다 종료되면 빈 공간이 생기는데 이때 빈 공간의 크기가 일정하지 않다는 문제가 있다. 이렇게 발생한 작은 빈 공간을 "단편화(Fragmentation)" 이라고 한다. 가변 분할 방식에서 발생하는 단편화는 조각이 프로세스의 바깥쪽에 위치하기에 "외부 단편화(External Fragmentation)"이라고 한다.
외부 단편화의 문제를 해결하기 위해서는 주로 "메모리 배치 방식(Memory Placement Strategy)"이나 "조각 모음(Defragmentation)"을 사용할 수 있다.
메모리 배치 방식은 작은 조각이 발생하지 않도록 프로세스를 배치하는 것이다. 선처리 방식에 해당하며 이때, 메모리 배치 방식에는 "최초 배치", "최적 배치", "최악 배치"가 있다.
- 최초 배치(First Fit): 단편화를 고려하지 않는 방식으로, 프로세스를 메모리의 빈 공간에 배치할 때 메모리에서 적재 가능한 공간을 순서대로 찾다가 가장 처음 발견한 공간에 프로세스를 배치하는 방식이다.
- 최적 배치(Best Fit): 메모리의 빈 공간을 모두 확인한 후 크기가 가장 비슷한 곳에 프로세스를 배치하는 방식이다.
- 최악 배치(Worst Fit): 빈 공간을 모두 확인한 후 가장 큰 프로세스를 배치하는 방식이다.
조각 모음은 조각이 발생했을 때 작은 조각들을 모아 하나의 큰 덩어리로 만드는 것이다. 후처리 방식에 해당한다. 메모리 통합이라고도 불린다. 조각 모음은 다음의 순서로 진행한다.
- 조각 모음을 하기 위해 이동할 프로세스의 동작을 멈춘다.
- 프로세스를 적당한 위치로 이동한다. 프로세스가 원래의 위치에서 이동하기에 프로세스의 논리 주소 값을 바꾼다.
- 위의 작업을 마치고 다시 프로세스를 시작한다.
고정 분할 방식
고정 분할 방식은 프로세스의 크기에 상관없이 메모리를 같은 크기로 나누기에 "페이징 메모리 관리 기법(Paging)"이라고 불린다. 현대의 메모리 관리는 페이징을 기본으로 한다. 고정 분할 방식은 일정하게 나뉜 메모리의 크기보다 작은 프로세스가 배치되면 낭비되는 공간이 생긴다. 이때, 일정한 크기로 나뉜 파티션 안쪽으로 작은 조각이 발생하는데 이와 같이 각 메모리 조각에 프로세스를 배치하고 공간이 남는 것을 "내부 단편화(Internal Fragmentation)"이라고 한다.
고정 분할 방식에서는 내부 단편화를 해결하기 위하여 조각 모음을 할 수 없고, 남는 공간을 다른 프로세스에 배정할 수 없기에 메모리를 나누는 작업을 신중하게 해야 한다.
버디 시스템 (Buddy System)
버디 시스템은 외부 단편화를 완화하는 방법으로, 가변 분할 방식과 고중 분할 방식의 중간 구조이다. 버디 시스템의 작동 방식은 다음과 같다.
- 프로세스의 크기에 맞게 메모리를 1/2로 자르고 프로세스를 메모리에 배치한다.
- 나뉜 메모리의 각 구역에는 프로세스가 1개만 들어간다.
- 프로세스가 종료되면 주변의 빈 조각과 합쳐서 하나의 큰 덩어리를 만든다.
버디 시스템은 가변 분할 방식처럼 메모리가 프로세스 크기대로 나뉜다. 그리고 고정 분할 방식처럼 하나의 구역에 다른 프로세스가 들어갈 수 없고 한 구역 내부에 조각이 생겨 내부 단편화가 발생한다. 효율적인 공간 관리 측면에서 보면 고정 분할 방식과 버디 시스템은 비슷하다. 그러나 고정 분할 방식이 메모리 관리 측면에서 더욱 단순하기에 버디 시스템보다는 고정 분할 방식을 더 주로 사용한다.