# 가상 메모리

물리적 메모리 부족 문제를 해결하는 기술

\


## 가상 메모리 등장 배경

#### 메모리

* 프로그램과 프로그램 수행에 필요한 데이터 및 코드를 저장하는 장치
* 크게 내부 기억장치인 `주기억장치`와 외부 기억장치인 `보조 기억장치`로 분류됨
  * `주기억장치`: DRAM, CPU 안에 있는 레지스터와 캐시 등
  * `보조 기억장치`: SSD, HDD 등

\


#### 메모리 부족 문제

* 프로세스를 실행시키기 위해 반드시 메모리(RAM)에 적재되어있어야 한다.
* 하지만 메모리보다 큰 용량의 프로세스, 또는 한번에 많은 프로세스를 실행시켜 메모리의 용량을 초과하게되면 실행되지 않는 문제가 생긴다.
* 그래서 애플리케이션을 실행하는데 얼마나 많은 메모리가 필요한지에 집중하지 않고, 대신 `애플리케이션을 실행하는데 최소한 얼마만큼의 메모리가 필요한가`에 집중하여 문제를 해결하고자 하였음
  * 해당 기법이 `가상 메모리 기법`
  * 메모리 접근은 순차적이고 지역화되어 있기 때문에 해당 접근 방식이 가능함

\


## 가상 메모리란?

* 개념
  * 프로세스 전체가 메모리에 올라가지 않더라도 실행 가능하도록 하는 것
    * 더 작은 양의 주소 공간으로 프로세스를 수행할 수 있음
  * 운영체제에서 실제 물리메모리(RAM)보다 큰 주소공간을 프로세스에게 제공하기 위해 사용되는 기술

\


* 제공하는 기능
  * 주기억장치의 효율적 관리
    * 메모리 용량 부족 이슈 해결
    * Cache를 이용하여 자주 사용하는 데이터만 RAM 영역을 유지하고, 나머지는 하드디스크에 보관함
  * 효율적인 메모리 관리
    * 유저는 물리 메모리 정보가 아닌 운영체제가 제공해주는 가상 메모리 공간만 신경쓰면 됨
    * 나머지 관리는 운영체제 내부에서 처리됨
  * 메모리 용량 및 안정성 보장
    * 프로세스 메모리 영역 간에 침범 이슈 해결
    * RAM에 대하여 무한한 가상 메모리 공간을 배정하여 프로세스들끼리 메모리 침범이 덜 일어나게 함
      * 운영체제가 가상 메모리 체계를 관리하기 때문에 프로세스 간 사용 영역이 겹치지 않도록 배정해주어 독립성을 보장함

\


### 기본 원리

![](https://media.vlpt.us/images/chappi/post/c006bc8a-b149-40c2-9cc0-c3fd841b9eff/1.png)\


* 프로그램의 논리적주소 영역에서 필요한 부분만 물리적 메모리(기억장치)에 적재하고, 올라가지 않는 나머지는 보조 기억 장치(디스크)에 위치하게 됨
  * 디스크가 RAM의 보조 기억장치처럼 작동하는 것
  * 빠르고 작은 기억장치(RAM)을 크고 느린 기억장치(디스크)와 병합하여, 하나의 크고 빠른 기억장치(가상메모리)처럼 동작하게 하는 것
  * 이때 물리 메모리와 보조 기억 장치간의 [스와핑(swapping)](https://github.com/jmxx219/CS-Study/blob/main/OperatingSystem/%EC%97%B0%EC%86%8D%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%ED%95%A0%EB%8B%B9.md#swapping%EC%8A%A4%EC%99%80%ED%95%91) 작업이 일어남
* 디스크를 사용하여도 실제로 프로세스가 실행될 수 있는 메모리 공간은 RAM 크기이고, 이 물리 메모리에 접근할 수 있는 가상 주소를 프로세스의 메모리에 저장함
  * 운영체제가 가상 메모리 공간을 프로세스에게 제공해줌으로써 프로세스는 자신을 모두 메모리에 적재했다는 착각을 하게 됨
    * 프로세스 입장에서 가상 메모리 공간도 물리 메모리 공간으로 인식하게 됨
  * 이후 CPU는 프로세스를 실행할 때는 가상 주소를 사용하고, 실제 해당 가상 주소에서 데이터를 읽고 쓸 때만 물리 주소로 접근해서 실행함

\


### 가상 주소와 물리 주소

![](https://github.com/jaepyo-Lee/OneLine/assets/74135929/217ca910-213b-4e70-9b01-c7dea6bf7dd6)\


* 가상 주소(논리 주소)
  * 프로세스가 참조하는 주소로, 프로세스마다 독립적으로 할당되며 자신만의 가상 주소 공간을 가짐
  * `논리 주소`라고도 함
    * 컴파일러 입장에서 코드와 변수의 주소는 프로그램 내에서의 상대적인 주소이므로 논리 주소라고 부르는 것이 적합함
    * 가상 메모리를 다루는 운영체제 입장에서는 프로세스의 가상 주소 공간내에서 사용되는 주소이므로 가상 주소라고 하는 것이 더 적합함
  * 프로세스가 읽고 쓸 수 있는 공간이 가상 주소 공간으로 제한되기 때문에 실제 물리 주소의 데이터가 수정되거나 동시에 접근해서 충돌할 일이 없음
* 물리 주소
  * 실제 메모리의 주소이며 하드웨어에서 직접 접근 가능한 주소
  * 시스템 전체적으로 공유되는 주소이며, 여러 프로세스가 공유 메모리 영역을 사용할 때 사용됨
  * 프로세스가 물리 주소로 접근하려면, 물리 주소를 가르키고 있는 가상 주소를 물리 주소로 변환해야 함(`mapping` 과정)
    * 이때 필요한 것이 `MMU`

\


#### MMU(Memory Management Unit, 메모리 관리 장치)

![](https://github.com/jmxx219/CS-Study/assets/52346113/6b5d98dd-75ab-4a62-a4cd-6283feb4b9ea)\


* CPU에 코드 실행시, 가상 주소 메모리 접근이 필요할 때 해당 주소를 물리 주소 값으로 변환해주는 하드웨어 장치
  * 하드웨어 장치를 이용해야 주소 변환이 빠르기 때문에 별도의 장치인 MMU를 사용함
* MMU를 사용하여 CPU가 각 메모리에 접근하기 전에 메모리 주소 번역 작업이 수행됨
  * 하지만 메모리를 하나하나 가상 주소에서 물리적 주소로 번역하면 작업 부하가 높아지게 됨
  * 따라서 MMU는 RAM(물리 메모리)을 여러 페이지(`page`)로 나누어 각 페이지 단위로 데이터를 처리함

\


> CPU는 가상 메모리를 다루고, 가상 메모리의 가상 주소에 접근시 MMU하드웨어를 통해 물리 주소로 변환되어 물리 메모리에 접근함

\


## 가상 메모리의 분할 방식

* 실제 메모리에 있는 물리 주소 0번지는 운영체제 영역이기 때문에 일반 프로세스가 사용할 수 없음
* 따라서 가상 메모리 시스템에서는 운영체제를 제외한 나머지 영역을 일정한 크기로 나누어 일반 프로세스에게 할당함
  * [메모리 분할 방식](https://github.com/jmxx219/CS-Study/blob/main/OperatingSystem/%EC%97%B0%EC%86%8D%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%ED%95%A0%EB%8B%B9.md#%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%97%B0%EC%86%8D%ED%95%A0%EB%8B%B9-%EA%B8%B0%EB%B2%95)은 크게 가변과 고정 분할 방식으로 나뉘는데, 가상 메모리 시스템에서도 동일함
  * 가상 메모리 시스템에서 가변 분할 방식을 이용한 메모리 관리 기법은 `세그먼테이션`, 고정분할 방식을 이용한 메모리 관리 기법은 `페이징`이라고 함

\


### 페이징 시스템

> 가상 메모리의 아이디어는 프로세스의 모든 데이터를 물리 메모리에 적재할 필요가 없다는 것이다.\
> 따라서 필요한 만큼만 물리 메모리에 올리는데, 이때 프로세스를 어떻게 나누어서 올리는가에 대한 다양한 아이디어 중 하나가 페이징 시스템이다.\
> [페이징 기법 참고](https://github.com/jmxx219/CS-Study/blob/main/OperatingSystem/%EC%97%B0%EC%86%8D%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%ED%95%A0%EB%8B%B9.md#%ED%8E%98%EC%9D%B4%EC%A7%95-%EA%B8%B0%EB%B2%95-paging)

\


* 개념
  * 가상 주소 공간과 매칭되는 물리 주소 공간을 크기가 동일한 고정된 조각(page)으로 분리하는 방법
  * 페이지 번호를 기반으로 가상 주소와 물리 주소의 매핑 정보를 기록해서 사용함
* 용어
  * frame: 물리적 메모리를 일정한 크기로 나눈 block(물리 메모리 단위)
  * page: 가상 메모리를 frame 동일한 크기로 나눈 block(가상 메모리 단위)
  * paing table: 가상 주소와 물리 주소 정보를 매핑한 표

\


#### Page Fault

![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2\&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4ET4w%2FbtqJijQWvRx%2FKRCE0x2vKlzGkJvzz7Bhm1%2Fimg.png)\


* 어떤 프로그램이 자신의 주소 공간(가상 메모리 공간)에는 존재하지만, 시스템의 RAM에는 현재 존재하지 않는 데이터 또는 코드에 접근을 시도할 경우 발생하는 현상([인터럽트](https://github.com/jmxx219/CS-Study/blob/main/OperatingSystem/Interrupt.md#%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-1))
  * 페이지가 보조기억장치에 존재하는 상황
* 페이지 폴트가 자주 일어날 경우 성능이 저하됨
  * 따라서 페이지 폴트를 최소화하기 위한 방법으로 `페이지 교체 정책`이 있음
  * 메모리가 꽉 차있을 때 기존 페이지 중 하나를 물리 메모리에서 보조 기억 장치로 내리고, 새로운 페이지를 방금 비워진 해당 물리 메모리 공간에 올림(스와핑 작업)
    * 이때 기존 페이지 중 어떤 것을 내리면 좋은지에 대한 알고리즘이 `페이지 교체 알고리즘`임
* 페이지 폴드 처리 과정
  1. CPU는 물리 메모리을 확인하여 페이지가 없으면 trap을 발생하여 운영체제에게 알림
  2. 운영체제는 CPU의 동작을 잠시 멈춤
  3. 운영체제는 페이지 테이블을 확인하여 가상 메모리에 페이지가 존재하는지 확인하고, 없으면 프로세스를 중단함
  4. 페이지 폴트이면, 현재 물리 메모리에 비어있는 프레임(Free Frame)이 있는지 찾음
  5. 보조 기억 장치에서 올리고자 하는 페이지를 찾고, 비어있는 프레임에 해당 페이지를 로드하고 페이지 테이블을 갱신함
     * 비어있는 프레임이 없다면 희생 프레임을 골라야 하는데, 이때 `페이지 교체 알고리즘`이 사용됨
  6. 중단되었던 CPU를 다시 시작함

\


#### 페이지 개수와 크기는 Trade-Off 관계

* page size를 작게 구성할 경우
  * 프로세스 당 page 수 증가 → page table의 크기 증가 → 더 많은 메모리를 차지하게 됨
* page size를 크게 구성할 경우
  * 내부 단편화의 발생 확률이 증가함
  * 사용하지 않는 부분도 메모리에 같이 올라가게 되면서 page fault가 증가함

\
\


***

참고

* https://eclipsemode.tistory.com/79
* https://ahnanne.tistory.com/15
* [가상 메모리 개요, 페이징](https://velog.io/@chappi/OS%EB%8A%94-%ED%95%A0%EA%BB%80%EB%8D%B0-%ED%95%B5%EC%8B%AC%EB%A7%8C-%ED%95%A9%EB%8B%88%EB%8B%A4.-14%ED%8E%B8-%EA%B0%80%EC%83%81-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B0%9C%EC%9A%94-%ED%8E%98%EC%9D%B4%EC%A7%95)
* [Demand Paging](https://palamore.tistory.com/339)
