가상 메모리

덤프버전 :

Virtual Memory

1. 개요
2. 기능
3. 기술적 설명
3.1. MMU (Memory Management Unit)
3.2. 페이지 (Page)
3.3. 페이지 폴트 (Page Fault)
4. 기능
4.1. 디스크 스왑
4.2. 메모리 압축
4.3. 또다른 방법
5. 기타
6. 참조



1. 개요[편집]


일반적으로 한 시스템의 여러 프로세스들은 CPU, 메인 메모리를 공유한다. CPU를 공유하는 부분에 대해서는 일반적으로 순서를 기다리느라 단지 느려질 뿐이고 심각한 오류는 발생하지 않는다. 그러나 프로세스들이 존재하는 메모리가 여유가 없이 지나치게 많은 요구에 의해 오염될 경우,[1] 프로그램의 논리와 무관하게 오류가 난다. 이를 방지하기 위한 기술이 바로 가상메모리이다.

이러한 가상메모리 기술은 사용자가 신경 쓸 필요 없이 OS 측에서 자동으로 작동하며 사용자가 프로세스를 올리고 내림에 있어서 역시 사용자가 신경 쓸 필요 없이 OS의 가상메모리를 활용하여 자동으로 메모리 관리를 위임할 수 있다는 장점이 있다.

가상메모리는 프로세스들에게 각각의 비어있는 메모리 영역을 부여한다. 그 메모리 영역은 처음부터 비어있는 상태다. 프로세스의 가상 메모리 접근은 결국 물리 메모리로의 접근으로 이어진다.


2. 기능[편집]


가상 메모리의 주요한 기능은 다음 3가지로 요약할 수 있다.

  • 메모리 관리의 단순화: 각 프로세스마다 가상메모리의 통일된 주소 공간을 배정할 수 있으므로 메모리 관리가 단순해진다.

  • 메모리 용량 및 안정성 보장: 한정된 공간의 램이 아닌 거의 무한한 가상메모리 공간을 배정함으로써 프로세스들끼리 메모리 침범이 일어날 여지를 크게 줄인다.[2]


3. 기술적 설명[편집]



3.1. MMU (Memory Management Unit)[편집]


현대의 CPU들은 모두 메모리 관리 유닛(MMU, Memory Management Unit)이라는 것을 내장하고 있다. 이 MMU라는 용어는 반드시 가상 메모리를 구현하는 유닛만을 얘기하는 것은 아니고, 뱅크 스위칭과 같은 방식으로 처리하는 경우에도 MMU라고 부를 수 있다. 이런 목적으로 별도의 칩이 있어서 CPU와 메모리 사이에 회로 연결로 구현되는 경우도 있다. 물론 현재는 CPU에 포함되어 있다.

여담으로 메모리 보호 유닛 (MPU, Memory Protection Unit)라는 MMU보다 한 단계 낮은 것도 존재한다. 주로 피처폰에 사용되는 CPU에 MMU 대신 내장된다.


3.2. 페이지 (Page)[편집]


가상 메모리의 주소 공간은 페이지(Page)라는 것으로 일정한 크기로 분할되어 있다. 페이지의 크기는 하드웨어에 의해 결정이 되며 운영체제는 이러한 페이지들을 페이지 테이블 안에 집어 넣어서 관리하고 있다. 프로세스마다 자신만의 페이지 테이블을 가지고 있다. (유저 메모리) 물론 운영체제도 역시 자신만의 페이지 테이블을 가지고 있다. (커널 메모리) 페이지 테이블은 운영체제에서 관리한다.

프로세스는 각자 독립된 가상 주소를 가진다. 예를 들어 A 프로세스는 0x1000라는 주소를 가질 수도 있고 동시에 B 프로세스는 0x1000라는 주소를 가질수도 있다. 만약 두 프로세스가 각자 0x1000라는 주소에 접근할 경우 CPU는 프로세스 (컨텍스트)마다 가지는 페이지 테이블을 참조한다.

페이지 테이블은 가상 주소와 물리 메모리의 실제 주소를 연결시켜주는 테이블이다. 가령 A 프로세스의 페이지 테이블에서 0x1000 주소에 대응되는 실제 주소는 0x30000 으로 나오고 B 프로세스의 페이지 테이블에서는 0x1000 주소에 대응되는 실제 주소가 0x40000인 것이다. 이렇게 되면 두 프로세스는 동일한 메모리 주소를 참조했지만 실제로는 MMU가 프로세스의 페이지 테이블을 참조해서 실제 물리 메모리 주소를 얻고 그 위치를 참조해서 가져오거나 쓰기를 한 것이다. 따라서 두 프로세스의 주소 공간이 겹치지 않고 독립적으로 실행될 수 있으며 프로그래머는 다른 프로세스의 주소 공간을 생각할 필요가 없어진다.

가상 메모리 공간은 비페이징 공간(Nonpaged Space)과 페이징 공간(Paged Space)으로 나뉘어져 있다. 비페이징 공간은 항상 물리 메모리에 존재하는 공간으로 페이징 파일로 옮겨지지 않는다. 반면 페이징 공간은 운영체제가 필요하지 않을 경우 물리 메모리에서 페이징 파일로 옮길 수도 있는 공간이다. 따라서 비페이징 공간은 페이지 폴트가 절대로 일어나지 않는다.


3.3. 페이지 폴트 (Page Fault)[편집]


물리 메모리의 모든 내용은 계속 저장해놓지 않는다. 운영체제는 사용되지 않는 페이지를 디스크에 있는 페이징 파일로 옮기게 된다. [3]

페이지 테이블에는 유효 비트라는게 있는데 이를 통해 페이지가 실제 물리 메모리에 존재하는지 알 수 있다. 프로세스가 가상 주소에 접근하게 되어 MMU가 페이지 테이블을 참조한 뒤 페이지를 확인해보는데 유효하지 않을 경우 페이지 폴트 (Page Fault)라는 트립을 발생시킨다. 페이지 폴트을 감지한 운영체제는 CPU의 동작을 잠시 중단시킨 뒤 해당 페이지를 페이징 파일에서 가져와서 물리 메모리의 비어있는 공간에 적재시키고 페이지 테이블을 최신화시킨 뒤 CPU의 동작을 재개시킨다.

따라서 사용되지 않는 페이지를 페이징 파일로 옮기는 것과 물리 메모리에 없는 페이지를 페이징 파일에서 가져와서 물리 메모리에 적재하는 일은 운영체제가 자동으로 수행한다. 다만 페이지 폴트는 그 과정상 디스크에 접근하기 때문에 파일 입출력이 발생하므로 성능이 하락된다.

페이지 폴트 발생 시 운영체제의 페이지 폴트 핸들러로 이동하므로 한 프로세스를 다른 프로세스로 전환하지 않는 IRQ, 즉 디스패처 레벨 이상에서는 페이지 폴트가 일어나서는 안된다. 페이지 폴트 핸들러가 실행될 수 없기에 곧바로 커널 패닉 직행이다.

따라서 커널에 붙여서 동작하는 드라이버의 경우 비페이징된 공간에서 할당된다. 물론 개발자가 일부를 페이징화할 수 있도록 설정할 수 있다.


4. 기능[편집]



4.1. 디스크 스왑[편집]


엄밀히 말하면 가상 메모리 기술과 디스크 스왑은 직접적인 연관이 없다. 하지만 역사적으로 가상 메모리 기술이 등장한 이유는 상술한 관리 편의성 등의 이유가 아니라 당시 메모리가 너무 비쌌기 때문에 보조기억장치를 메모리로 쓰려는 이유 하나였다. 메모리의 가격이 싸진 현재는 디스크 스왑을 할 필요가 없을 정도로 넉넉한 메모리를 구비하는 것도 불가능한 일이 아니지만, 이러한 역사적인 맥락으로 인해 가상 메모리에 대해 논할 때는 디스크 스왑을 같이 이야기하지 않을 수 없다.

가상 메모리 기술은 실제로 존재하지 않는 메모리 영역을 할당하는 것이 가능하지만, 정말 메모리가 부족하다면 페이지 폴트(Page Fault)가 발생하여 애플리케이션이 죽든 시스템이 죽든[4] 해 버린다. 이런 문제를 해결하기 위해서 나온 것이 '디스크 스왑'으로, 이는 메모리의 일부분을 디스크에 저장해 두었다가 그 영역을 읽고 쓰고자 할 때 디스크에서 불러와서 메모리에 적재하는 방식이다. 주메모리(램, 캐시 메모리)의 가격이 워낙 비싸고 보조 저장장치(하드디스크, SSD)는 상대적으로 훨씬 싸기 때문에 등장한 방법.

이러한 디스크 스와핑을 사용하는 경우 전체적인 시스템 성능이 다소 저하된다. 보조메모리가 주메모리보다 느려서 병목현상이 발생하기 때문.[5] 설령 주메모리와 보조메모리의 속력이 같다고 해도 메모리 리스트에서 계속해서 대조하여 실제 메모리 위치로 맵핑하기 때문에, 맵핑에 걸리는 시간이 전체적인 오버헤드를 점유하여 태생적으로 주메모리보다 속도가 느릴 수 밖에 없다. 이런 문제를 조금이나마 극복하기 위해서, 메모리 스왑을 할때 메모리를 압축하여 용량을 감소시키는 ZRAM 같은 기술이 사용된다.대신 필요한 경우 소프트웨어를 유연하게 사용(…이라기보단 억지로라도 구동 가능.)할 수 있다는 것이 장점일 것이다.

SSD가 일반 사용자에게 보급되지 않았던 시기에는 스와핑에 쓸 수 있는 보조기억장치가 HDD밖에 없었으므로 자연스럽게 '디스크 스왑'이라는 용어가 정착했지만, 디스크 형태가 아닌 SSD나 USB 메모리 등의 다른 저장 매체도 얼마든지 스왑에 사용할 수 있다.

주메모리(DDR 1 ~ 3)와 보조메모리(HDD, eMMC, USB 메모리)의 속도 차이가 심하게 나던 시절에는 스왑에 사용된 보조 메모리가 병목 현상을 일으켜 시스템 성능을 심각하게 저하시키는 경우가 많았기 때문에 가상 메모리나 스왑 기능을 아예 끄는 것이 추천되기도 했다. 그러나 현대의 보조메모리는 속도가 비약적으로 발전해(NVMe, UFS) 병목 현상을 일으킬 우려가 적으므로 현재는 대부분의 시스템이 스와핑 기능을 적극 활용하고 있다.


4.2. 메모리 압축[편집]


zRAM과 zswap은 Linux에서 제공하는 스왑 기능이며, 램공간을 압축해서 응용하는 기술이다.

zRAM은 램영역을 압축해서, 디스크처럼 사용할 수 있는 기능이며, 여기에 파일시스템이나 swap등을 적용해서 사용할 수 있다.
zswap은 여전히 기존의 디스크 스왑을 필요로 하지만, 중간에 압축된 램을 이용해 버퍼를 제공하므로, 디스크의 입출력을 줄이는 용도로 사용된다.

zRAM의 경우에는 보조 저장장치를 사용을 하지 않기 때문에, 디스크 스왑에 비해 빠르게 동작하고, 플래시 메모리의 수명에 크게 영향을 끼치지 않는다.

하지만, 메모리를 과다하게 사용할 때에는 압축에 따른 오버헤드가 발생하므로 CPU 사용률이 증가하며, 스마트폰과 같은 휴대용 기기에서는 배터리 사용량도 증가한다는 단점이 존재한다.

안드로이드(운영체제)에서도 리눅스 기반이다보니 이러한 스와핑 기능을 제공한다. 메모리가 부족한 저가형 기기를 위해 Android 4.4부터 zRAM이 적용되었으나[6], Android 6.0부터는 넥서스 5X넥서스 6P와 같은 플래그쉽 기기에 적용[7]되기 시작되었고, 중국 스마트폰 제조사들도 RAM 용량 문제를 해결하기 위해 자사 스마트폰에 가상 메모리 기술을 도입하거나 도입 계획하면서 스마트폰 업계의 트렌드로 자리잡고 있다. # 삼성전자삼성 갤럭시에서 2021년부터 디바이스 케어의 RAM 메뉴에서 RAM Plus라는 이름으로 해당 기능이 제공되고 있다. 마이크로소프트Windows 10 TH2 버전 부터 메모리 압축 기술을 적용하고 있으며 메모리 압축 기술의 적용 초기에는 시스템 부하가 너무 커서 문제가 되기도 했으나 이후 해결되었다. 애플OS X Mavericks (10.9)iOS 7 부터 적용중인 것으로 알려져 있다.[8] 이에 더해 iPadOS 16부터는 M1/M2 아이패드 한정으로 직접 설정이 가능해졌다.


4.3. 또다른 방법[편집]


디스크 스왑은 DRAM 메모리의 일부분을 보조 저장장치에 저장하고, DRAM 의 해당 영역을 사용하는 것이다.

그런데, SSD의 성능이 향상되고, 옵테인 메모리같은 고성능 장치가 나오자, 아예 SSD의 일부 영역에 메모리 주소를 부여하고 그냥 메모리 처럼 쓰는 방식도 사용되고 있다. 스왑에 대한 오버헤드가 감소한다는 장점은 있으나, DRAM 에 비해서는 여전히 느리기 때문에 성능이 크게 향상되는 것은 아니다.


5. 기타[편집]


가상 메모리 기법은 디스크를 메모리로 사용하는 디스크 페이징(스왑)과는 직접적으로 연관이 없다. 여기서 가상(Virtual) 의 의미는 디스크를 가상의 RAM 처럼 쓴다는 의미가 아니라, 각 프로세스마다 실제 물리 메모리가 아닌 가상의 주소 공간을 보이게 한다는 의미이다. 사실 넓게 보면 메모리의 내용을 디스크에 임시로 저장하는 개념 자체는 별로 특이한 것도 아니고 이론적으로는 가상 메모리를 사용하지 않는 시스템에서도 구현할 수 있다.[9] 이렇게 용어가 혼동되어 쓰이는 이유는 과거 Windows 에서 이러한 디스크 스왑 설정을 "가상 메모리" 라고 번역 해놓은 것을 아직까지 그대로 사용하고 있기 때문이다.

램의 크기가 32GB~128GB 정도로 충분히 크다고 판단하여 가상 메모리를 사용할 필요가 없는 것이 아니므로, 가상 메모리 기능을 비활성화하는 것은 좋지 않다. 특히 20년 이상된 오래된 최적화 팁이랍시고 가상 메모리를 비활성화하는 방법이 많이 소개되었는데 이는 과거 CPU와 램, 하드디스크 사이의 읽기 쓰기 속력 차이가 워낙 많이 나서 병목현상이 나고 SSD는 용량이 너무 작았던 시절에야 살짝 통하던 방법이라 현대 컴퓨터와는 맞지않고 오히려 에러가 더 증가하는 개악된 방법이다. 최근에는 SSD의 발달로 CPU와 주기억장치(램), 보조기억장치(NVMe 이상의 SSDUFS)간의 병목현상이 완화되어 오히려 보조기억장치 활용을 늘리는 추세라서 해당 최적화를 함부로 따라해서는 안된다.

Linux와 같은 Unix-like OS의 경우 스왑을 해제하여도 메모리가 실제로 모두 사용되어야 메모리 부족이 뜨는 것에 비해 Windows의 경우 스왑이 활성화 되어 있는 상태에선 다른 OS들과 같이
malloc()
등으로 메모리 할당을 요청하였을 때 가상 메모리 공간에서 커밋이라는 이름으로 할당되게 되고 이 공간에 실제로 값이 쓰여지기 시작 할 때 실제 메모리 사용률이 올라가기 시작하는것에 비해 해당 옵션을 끄는 경우 사용하지 않고 단순 할당 요청만 하여도 OS가 프로세스를 위해 할당 받은만큼 점유해 버린다.
이 때문에 4GB 메모리가 장착된 시스템에서 A, B 프로그램이 각각 4GB씩 할당받고 실제로는 1GB만 사용하는 상황일 때 스왑이 활성화 되어 있으면 Windows는 2GB 메모리를 사용중이라고 리포트 하게 되고 (8GB 커밋) 동작에 아무 문제가 없지만 스왑을 해제하게 되면 A프로그램이 4GB를 할당받으면 OS가 모든 메모리를 사용중인것으로 리포트하게 되며 B프로그램은 메모리를 할당받는것이 불가능해 메모리 부족 오류가 뜨게 된다. (
malloc()
returns
NULL
)

자세한 내용은 최적화 프로그램 문서를 참고.


6. 참조[편집]




파일:크리에이티브 커먼즈 라이선스__CC.png 이 문서의 내용 중 전체 또는 일부는 2023-11-09 04:15:59에 나무위키 가상 메모리 문서에서 가져왔습니다.

[1] 의도치 않게 덧씌워진 경우 등을 시스템적 용어로 오염이라 칭한다. 쉽게 생각하자면 A팀, B팀, C팀이 강당에 모여있는데 A,B,C팀 인원이 지나치게 많아진 나머지 C팀 인원 일부가 인파에 몰려 A팀으로 가버리고, A팀도 덩달아 B팀으로 가버리는 중구난방, 흡사 시장통과 같은 상황을 생각하면 된다. 당연히 서로 섞여버렸기 때문에 A팀 조장이 "A팀 18번!"을 불렀을 때 대답이 없거나(해당 메모리의 주소 호출 불가) 또는 대답을 하더라도 얼떨결에 A팀의 18번 자리에 서있는 C팀의 18번이 대답을(잘못된 메모리 참조) 하게 되는 것이다.[2] 사실상 없앤다고 봐도 무방하나 완전히 없애는 경우는 없다.[3] Windows에서는 'pagefile.sys'라는 이름의 페이지 파일을 사용한다.[4] 코드명 0x00000050[5] 시중에서 흔히 구할 수 있는 DDR4 RAM의 랜덤 액세스 속도는 2022년 기준 최고의 성능을 가진 PCIe 4.0 NVMe 규격 SSD보다 무려 20~30배 이상 빠르다. 그나마 인텔의 옵테인 메모리가 DRAM과의 랜덤 액세스 속도 격차가 3~5배 정도로 적은 편이지만, 이 쪽은 보급에 실패해 일반인이 사용할 일이 거의 없는 물건이다.[6] 출처: #[7] 출처: Nexus 5X, Nexus 6P[8] WWDC 2018 iOS Memory Deep Dive 발표 영상: #[9] 애초에 개발자가 명시적으로 구현한다면 어느 시스템이든 안될 건 없으나(이건 데이터 백업이나 다름 없다) 당연히 그런 경우는 포함하지 않으며 응용 프로그램 개발자가 따로 고려하지 않아도 묵시적으로 처리되는 경우만 얘기하는 것이다.