[운영체제] 5. 가상 메모리
본 글은 '이것이 취업을 위한 컴퓨터 과학이다 with CS 기술 면접' 책을 읽고 정리한 글입니다.
논리 메모리와 물리 메모리
CPU가 프로세스를 처리할 때 보는 주소 값과 실제 메모리의 주소 값은 다르다. 프로세스가 보는 메모리 영역을 논리 메모리 영역이라 하고, 실제로 사용되는 메모리 영역을 물리 메모리 영역이라고 한다. 그리고 CPU가 프로세스를 실행할 때 보는 주소 값을 논리 주소, 메모리의 하드웨어 상 실제 주소를 물리 주소라고 한다.
논리 주소는 프로세스마다 0번지부터 시작하는 주소 체계이다. 따라서 물리 주소의 번지 수는 중복될 수 없지만, 논리 주소의 번지 수는 중복으로 존재할 수 있다.
이처럼 CPU가 프로세스를 실행할 때 사용하는 주소 값과 실제 하드웨어 상의 주소 값이 다르므로 반드시 논리 주소와 물리 주소 간의 변환이 필요하다. 이때 논리 주소를 물리 주소로 변환하는 역할을 하는 것이 메모리 관리 장치(MMU, Memory Menagement Unit)이다.
MMU는 CPU에 위치하며, CPU에서 메모리에 접근하기 전에 MMU를 거쳐 논리 주소에 해당하는 물리 주소를 얻는다.
흐름을 정리해보자면, CPU는 프로세스를 실행할 때 PCB에 저장된 정보 중 프로그램 카운터(PC)를 참조해 다음에 실행할 명령어의 주소를 얻게 되는데 이 주소가 논리 주소이다. CPU는 이 논리 주소를 MMU를 통해 물리 주소로 변환한 후, 해당 물리 주소에 위치한 메모리에서 명령어를 받아와 실행하게 된다.
스와핑
메모리에 적재된 프로세스들 중 현재 실행되고 있지 않은 프로세스들도 있을 수 있다. 이런 프로세스들을 임시로 스왑 영역이라고 하는 보조기억장치의 일부인 영역으로 쫓아내고, 생긴 메모리 상의 빈 공간에 다른 프로세스를 적재하여 실행하는 것을 스와핑이라고 한다.
현재 실행되고 있지 않은 프로세스가 스왑 영역으로 옮겨지는 것을 스왑 아웃, 스왑 영역에서 다시 메모리로 옮겨오는 것을 스왑 인이라고 한다.
이처럼 스와핑이 발생할 때 프로세스를 메모리 상 빈 공간에 적재하는데, 메모리 상 빈 공간이 여러 개라면 어디에 적재를 해야할까??
비어 있는 메모리 공간에 프로세스를 할당하는 방법을 알아보자.
연속 메모리 할당
프로세스들이 메모리에 연속적으로 할당되는 방식을 연속 메모리 할당이라고 한다.
연속 메모리 할당은 고정 분할 방식과 가변 분할 방식이 있다.
고정 분할 방식
고정 분할은 메모리 영역을 분할한 뒤 각 영역에 프로세스를 할당하는 방식이다. 이 방식은 메모리에 올릴 수 있는 프로세스의 수와 각 프로세스의 크기가 제한된다는 단점이 있고, 단편화 문제가 발생할 수 있다.
예를 들어, 아래 그림을 보면 8MB의 공간과 2MB의 공간을 합치면 프로세스 7을 적재할 수 있지만, 공간이 분리되어있으므로 할당할 수 없는데 이런 경우를 외부 단편화라고 한다. 정리하자면 외부 단편화는 비어있는 메모리 공간보다 크기가 큰 프로세스를 적재하기 어려운 상황을 말한다.
그리고 프로세스 3과 4처럼 분할된 크기보다 작은 프로세스가 할당되어 메모리 공간이 남는 경우를 내부 단편화라고 한다.
가변 분할 방식
가변 분할은 할당할 프로세스의 크기에 따라 메모리 공간을 분할하는 방식으로, 가용 메모리 공간에서 프로세스가 로드될 수 있는 메모리 공간을 찾는다. 메모리 할당 알고리즘으로는 최초 적합, 최적 적합, 최악 적합이 있다.
1. 최초 적합 (first-fit)
가용 메모리 공간에서 프로세스 크기만큼 비어 있는 메모리 공간을 찾아 차례대로 프로세스를 로드한다.
2. 최적 적합 (best-fit)
할당하려는 프로세스 크기 이상인 가용 메모리 공간 중 가장 작은 공간에 프로세스를 할당한다. 이 방식은 가용 메모리 공간을 모두 탐색하여 찾아야 한다.
3. 최악 적합 (worst-fit)
할당하려는 프로세스 크기 이상인 가용 메모리 공간 중 가장 큰 공간에 프로세스를 할당한다. 이 방식 또한 가용 메모리 공간을 모두 탐색해야 한다.
비연속 메모리 할당
비연속 메모리 할당은 프로세스의 메모리 영역을 나눠서 메모리 공간에 저장하는 방법으로, 페이징과 세그먼테이션 방식이 있다.
페이징
페이징 기법은 프로세스의 논리 메모리 영역을 페이지라는 일정한 단위로 나누고, 물리 메모리 영역을 페이지와 일정한 크기의 프레임으로 나누는 방식이다.
이 방식으로 메모리를 할당하면 외부 단편화가 발생하지 않는다. 하지만 프로세스의 크기가 페이지 수로 나누어 떨어지는지는 보장하지 않는다. 따라서 프로세스의 크기가 마지막 페이지가 페이지의 사이즈보다 작을 수 있고, 이로 인해 내부 단편화 문제가 발생할 수 있다.
예를 들어, 프로세스의 크기가 7MB이고 한 페이지의 크기가 3MB라고 해보자. 페이지1, 페이지2는 각각 3MB씩 할당하면 되지만, 마지막 남은 1MB를 3MB 사이즈의 페이지에 할당하면 2MB가 남으므로 내부 단편화가 발생하는 것이다.
페이징 방식은 페이지를 비연속적으로 할당한다고 했는데 그렇게 되면 CPU는 다음에 실행할 페이지의 위치를 찾기 어렵다. 따라서 페이지와 프레임을 매핑하는 과정이 필요하다. 이 역할을 하는 것이 페이지 테이블이다.
페이지 테이블
페이지 테이블은 페이지 번호와 그에 대응되는 프레임 주소 값을 저장한다. 덕분에 CPU는 페이지 번호만을 가지고 프레임 위치를 알 수 있다. 프로세스마다 각자의 페이지 테이블 정보를 가지고 있으며, 이는 각 프로세스의 PCB에 저장된다.
세그먼테이션
세그먼테이션 기법은 프로세스의 메모리 영역을 일정한 크기의 페이지가 아닌 가변적인 크기의 세그먼트 단위로 분할해 메모리를 할당하는 방식이다.
세그먼트는 페이지와 달리 크기가 균등하지 않으므로 프로세스의 할당과 해제를 반복하다보면 외부 단편화 문제가 발생할 수 있다.
가상 메모리
만약 프로세스를 실행할 때 프로세스의 전부를 메모리에 로드해야한다면, 물리 메모리 크기보다 큰 프로세스는 실행할 수 없다. 컴퓨터의 메모리가 8GB일 때 여러 프로그램을 실행하게 되면 8GB는 금방 넘을 것이다. 그렇지만 실제로 실행해보면 8GB 이상도 실행이 가능하다는 것을 알 수 있다. 이처럼 한정된 메모리 공간에서 동시에 많은 프로그램을 실행하기 위해 나타난 개념이 가상 메모리이다.
우선 비연속 메모리 할당 기법을 사용하면 프로세스의 메모리를 나누어 저장할 수 있다는 것을 안다. 가상메모리는 프로세스의 일부만 메모리에 로드하고, 나머지는 디스크에 둔 상태로 프로세스를 실행하는 방식이다.
요구 페이징
페이징 기법에서 프로세스를 페이지 단위로 나누어 저장했다면, 요구 페이징(demand paging)은 프로세스에서 필요한 페이지만 메모리에 로드하는 방식이다. 초기에 필요한 영역만 로드한 후 다른 영역은 요청이 올 때 메모리에 로드한다.
프로그램을 실행하다가 물리 메모리에 필요한 페이지가 없을 수 있는데 이를 페이지 폴트라고 한다. 페이지 폴트가 발생하면 디스크에서 필요한 페이지를 스왑 인 한다.
필요한 페이지들을 메모리에 적재하다보면 언젠가는 메모리가 가득 차게 될 것이다. 메모리가 가득 찬 상황에서 추가적으로 페이지를 적재해야 한다면 메모리에 적재된 일부 페이지를 스왑 아웃해야 한다. 이때 내보낼 페이지를 결정하는 방법이 페이지 교체 알고리즘이다.
페이지 교체 알고리즘
FIFO 페이지 교체 알고리즘
FIFO(First In First Out) 알고리즘은 메모리에 가장 먼저 적재된 페이지부터 스왑 아웃하는 방식이다.
최적 페이지 교체 알고리즘
최적 알고리즘은 앞으로의 사용 빈도가 가장 낮은 페이지를 교체하는 알고리즘이다. 가장 좋은 페이지 교체 방법이지만 앞으로 가장 적게 사용할 페이지를 미리 예측하기 어렵기 때문에 구현이 어렵다.
LRU 페이지 교체 알고리즘
LRU(Least Recently Userd) 알고리즘은 가장 적게 사용한 페이지를 교체하는 알고리즘이다.
스레싱
스레싱은 동시에 일정 수 이상의 프로그램을 실행했을 때 오히려 CPU 이용률이 떨어지는 상황을 말한다.
가상 메모리 환경에서 동시에 여러 프로그램을 실행할 때, 프로그램 수가 일정 수 이상이 되면 페이지 폴트가 자주 일어난다. 그에 따라 프로세스가 실제로 실행되는 시간보다 페이징에 더 많은 시간을 소모하게 되면서 CPU 이용률이 떨어진다.
스래싱을 예방하려면 워킹 세트를 설정하는 방법이 있다. 워킹 세트는 지역성을 기반으로 자주 사용하는 페이지를 저장해두는 것을 의미한다.