가상 메모리

큰숲백과, 나무를 보지 말고 큰 숲을 보라.

가상 메모리(Virtual Memory)는 컴퓨터주기억 장치(Main Memory)를 CPU 상에서 돌아가는 모든 프로세스들이 공유할 수 있도록 물리적인 메모리에 적절히 할당할 수 있도록 추상적인 메모리 공간을 프로세스들에게 부여하는 기법이다. 하드웨어로는 MMU(Memory Management Unit) 등의 가속 장치만 제공하고 운영체제 별로 메모리 공간을 프로세스 별 메모리 공간에 적절하게 매핑하는 알고리즘을 사용하여 메모리 관리법을 단순화하고 프로세스 간의 메모리 공간 침범을 방지하는 데에 효과적이다.

그래서 가상 메모리를 사용할 경우 물리 메모리의 데이터 용량 제약을 크게 완화할 수 있으며 여러 프로세스에게 메모리 공간을 구분하여 제공하기 용이하다는 점 때문에 현대 컴퓨터 운영체제들이 적극적으로 이용하고 있다. 여기에 보조 기억 장치에 일부 프로세스 또는 프로세스 내부의 데이터를 밀어 넣고 중요한 코드 및 데이터만 주 기억 장치에 상주하는 기법(예: 메모리 스왑)과 결합하여 프로그램이 실행 시 주 기억 장치에 올려야 하는 데이터 크기를 줄이는 데에도 가상 메모리가 유용하다.

작동 방식[편집 | 원본 편집]

가상 메모리의 구현은 크게 세그먼테이션과 페이징으로 나뉜다. 초기에는 구역을 나누지 않고 바이트 단위로 연속해서 올리거나(Single Contiguous) 메모리 영역을 일정한 단위로 분할하여 프로그램을 주 기억 장치에 올렸으나 단편화(할당한 메모리 구역 내에 프로그램이 안 쓰는 영역이 발생하는 내부 단편화와 여러 프로그램 사이에 자잘하게 끼어버린 여분의 공간에 새 프로그램을 넣을 수 없는 외부 단편화 등) 문제로 인해 이 두 가지 방법이 제시되었다.

세그먼테이션은 메모리 공간을 용도에 따라 나누는 방법이다. 코드, 데이터, 스택 등의 세그먼트 공간을 두고 프로그램을 메인 메모리에 적재할 때 자신이 실행하는 프로그램을 용도별로 나누어 해당하는 세그먼트 공간에 배치한다. 만일 데이터를 읽고 쓸 때 지정된 세그먼트 공간의 범위를 넘으면 세그먼테이션 폴트가 발생한다. 이 방식은 내부 단편화 문제에 대해서는 페이징에 비해 발생 가능성이 매우 낮아 나은 편이나 메모리 스왑이 매우 어렵거나 큰 세그먼트 크기로 인해 PC에서는 성능 향상이 무의미한 수준이고 각 용도 별 메모리 영역의 외부 단편화 해결이 매우 어렵다는 문제로 현재는 구식 취급되어 PC에서는 사실상 페이징으로 대체된 메인 메모리 공간 관리 방식이 되었다.

페이징은 2의 제곱수 바이트(보통 4KB~1GB 사이)로 일정한 메모리 공간 단위인 페이지 프레임으로 메모리 공간을 분할한 다음 개별 페이지들을 관리하는 페이지 테이블을 프로세스들에게 각각 줘서 프로그램을 메인 메모리에 적재할 때 용도에 따라 페이지 주소를 테이블에서 찾고 플래그를 설정하여 해당 페이지의 특성과 용도(예: 코드가 적재된 페이지는 읽기만 가능하도록 세팅)를 정할 수 있다. 페이지는 세그먼테이션과 달리 순차적으로 실행해야 하는 코드를 메모리 공간에 불연속적으로 배치할 수 있어 메모리 공간 관리의 자유도가 높고, 외부 단편화에 한해[1] 메모리 공간을 낭비하는 일을 없앨 수 있으며 페이지를 디스크로 스왑하는 방식으로 더 많은 프로그램을 한 번에 실행할 수 있다.

페이지 테이블의 경우 x86의 예를 들자면 PTBR, PTLR 같은 특수 레지스터로 위치와 사이즈를 정하는 방식을 취한다. 그리고 프로세스마다 고유의 페이지 테이블을 가지며 Process Control Block에 프로세스 별 페이지 테이블의 위치를 가리키는 포인터가 저장되어 컨텍스트 스위치가 발생할 때마다 교체된다.

페이지 주소를 비트 단위로 나누어 멀티 레벨 페이지 테이블 구조를 만들 수 있다. 이러면 계층적인 메모리 공간 관리가 가능하여 넓은 범위의 메모리 공간과 좁은 범위 또는 개별 페이지의 메모리 공간의 특성을 따로 설정할 수 있으며, 페이지 테이블로 표시할 수 있는 메모리 공간 특성 세팅 가짓수를 늘릴 수도 있다. 리눅스의 경우는 PC용 RAM의 모듈 당 용량 증가 추세를 따라 2020년대 현재 5단계 레벨의 주소 체계까지 도입되었다.

덤으로 페이징 기법은 최소 메모리를 2번 접근해야 하므로(실제로 접근할 메모리 위치에 더해 페이지 테이블들에 접근하는 사이클이 추가된다) 페이지 테이블을 캐싱하는 SRAM인 Translation Lookaside Buffer(TLB)라는 특수한 캐시 메모리를 CPU에서 지원하는 경우가 있다.

페이지 교체 알고리즘[편집 | 원본 편집]

메모리 스왑(디스크 스왑)[편집 | 원본 편집]

한편 현재 실행하거나 참조하지 않는 페이지를 주 기억장치에서 보조 기억 장치로 보내고 그 자리에 더 많은 프로그램을 올리는 기법을 메모리 스왑이라고 한다. 메모리 스왑된 프로그램 코드는 페이지 파일 또는 스왑 파티션 내에 저장되며, CPU가 페이지 폴트 예외를 일으키면 다시 주 기억 장치로 가져온다. RAM이 같은 무게의 금보다 비싸던 예전이나 64비트 컴퓨팅을 필수로 요구할 정도로 램 용량이 커진 현대에도 더 많은 프로그램을 주 기억 장치에 실어 CPU가 실행하도록 하기 위해 메모리 스왑은 잘만 쓰이고 있다.

그렇다고 아무렇게나 스왑을 해버리면 주 기억 장치에 비해 긴 레이턴시로 느려 터진 보조 기억 장치로 불필요하게 많이 스왑을 하여 프로그램 실행 성능이 저하되는 쓰레싱(Thrashing)이 발생하기에 Locality 개념을 이용한 페이지 프레임의 워킹 셋(Working Set)[2]을 설정하여 중요하고 자주 실행하거나 참조하는 페이지 프레임은 자주 스왑되지 않도록 한다. Locality에는 시간적 지역성(일정 시간 동안 특정 페이지에 자주 접근하는 경향)과 공간적 지역성(특정 위치의 페이지들에 자주 접근하게 되는 경향)이 있어 루프 내 코드나 시스템 콜 같은 상황은 코드가 담긴 페이지 프레임들을 워킹 셋으로 할 수 있다.

  1. 내부 단편화는 발생 가능하기에 주로 적재하는 프로그램 특성에 페이징 단위를 최대한 맞추는 것으로 단편화의 최소화만 가능하다
  2. 다음 논문에서 제시된 개념이다: Denning, Peter J. (2021-02-02). "Working Set Analytics". ACM Computing Surveys. Association for Computing Machinery (ACM). 53 (6): 1–36. doi:10.1145/3399709. ISSN 0360-0300.