---
# System prepended metadata

title: 가상메모리
tags: [과외(기태)]

---

# 가상메모리

가상 메모리는 시스템의 메모리 관리 기법 중 하나로 프로세스가 물리적 메모리보다 큰 메모리를 사용할 수 있게 해준다. 프로세스는 가상 메모리에 접근하고, 실제로 필요한 페이지만 물리적 메모리에 올라가게 된다. 이렇게 함으로써 물리적 메모리보다 큰 프로세스를 실행할 수 있게 되고, 더 많은 프로세스를 실행할 수 있게 된다.

## 연속 메모리 할당

![image](https://hackmd.io/_uploads/SynNmt4Cp.png)

- 연속 메모리 할당은 프로세스가 메모리에 연속적으로 할당되는 것을 의미한다.
- 프로세스가 메모리에 완전히 로드될 때 연속적인 메모리 블록을 할당받는다

### 스와핑

![image](https://hackmd.io/_uploads/SkucXKECp.png)

- 스와핑은 메모리 관리 기법 중 하나로, 프로세스를 메모리와 보조 기억장치 (하드디스크) 사이에서 교체함으로써 메모리 사용을 최적화한다.
  - 즉, 하드디스크를 메모리처럼 사용하는 것이다.
  - 이 영역을 **스왑 영역**이라고 한다.
- 스와핑을 통해 시스템은 더 많은 프로세스 메모리를 동시에 처리할 수 있게 되며, 사용되지 않는 프로세스는 보조기억장치로 이동하여 많은 메모리를 절약할 수 있게 한다.
- 스와핑을 사용해서 실제 메모리보다 더 많은 양의 프로세스들을 실행시킬 수 있다.

스와핑의 기본 원리는 다음과 같다

![image](https://hackmd.io/_uploads/BkM3QtN0T.png)

1. 운영체제는 현재 메모리에서 사용되지 않는 프로세스의 섹션을 선정한다
2. 해당 프로세스는 하드 디스크 같은 보조 기억장치로 이동한다 (스왑 아웃)
3. 필요할 때 다시 메모리로 불러와 실행한다 (스왑 인)

이 과정은 메모리의 효율적 사용을 가능하게 하지만 스와핑 과정에서 발생하는 시간 지연이 성능에 영향을 줄 수 있다는 점을 고려해야 한다

### 메모리 할당

![image](https://hackmd.io/_uploads/H1atNKECa.png)

연속 메모리 할당에서는 메모리가 프로세스에게 연속적인 블록으로 할당된다. 이를 위헤 여러 가지 기법이 있지만 일반적인 세 가지는 다음과 같다

- 최초 적합 (First Fit)
- 최적 적합 (Best Fit)
- 최악 적합 (Worst Fit)

#### 최초 적합 (First Fit)

![image](https://hackmd.io/_uploads/BJ95VFV06.png)

- 메모리의 시작부분부터 검사하여 프로세스가 들어갈 수 있는 첫 번째 공간에 할당한다

#### 최적 적합 (Best Fit)

![image](https://hackmd.io/_uploads/Bk3hNtV06.png)

- 모든 가능한 공간을 검사하여 프로세스를 수용할 수 있으면서 가장 작은 공간에 할당한다
- 메모리의 낭비를 줄일 수 있지만, 검색 시간이 오래 걸릴 수 있다

#### 최악 적합 (Worst Fit)

![image](https://hackmd.io/_uploads/SkAtsKNAp.png)

- 가장 큰 공간에 프로세스를 할당한다
- 빠르게 공간을 찾을 수 있지만 큰 메모리 공간의 낭비로 이어질 수 있다

각 방식은 메모리 할당의 효율성과 성능에 다른 영향을 미치므로, 상황에 따라 적절한 방식을 선택해야 한다.

### 외부 단편화

![image](https://hackmd.io/_uploads/S1suE5ECa.png)

- 연속 메모리 할당의 주요 문제 중 하나는 외부 단편화이다.
- 이는 할당된 메모리 블록 사이에 사용되지 않는 작은 공간이 생기는 현상으로, 시간이 지남에 따라 메모리 공간이 점점 더 조각화되며, 충분히 큰 메모리 블록이 존재함에도 불구하고, 프로세스를 위한 충분한 연속 공간을 찾을 수 없게 되는 상황을 만든다.

![image](https://hackmd.io/_uploads/rJ4JrtNC6.png)

외부 단편화를 해결하기 위한 방법으로는 컴팩션(메모리 내의 모든 프로세스를 재배치하여 연속된 공간을 만드는 것), 크기 조정(프로세스의 메모리 요구에 따라 할당된 메모리 크기를 조정하는 것), 또는 비연속 메모리 할당 방식으로의 전환 등이 있다.

연속 메모리 할당은 그 구현의 단순함으로 인해 초기 운영 체제에서 널리 사용되었지만, 외부 단편화와 같은 문제로 인해 현대의 운영 체제에서는 주로 비연속 메모리 할당 방식인 페이징 또는 세그먼테이션을 사용한다. 이러한 방식은 메모리를 더 효율적으로 사용할 수 있게 하지만, 복잡성이 증가한다는 단점이 있다.

## 페이징을 통한 가상 메모리 관리

![image](https://hackmd.io/_uploads/r17mSKV0p.png)

컴퓨터 시스템에서 메모리 관리는 매우 중요한 역할을 한다. 특히, 페이징 시스템은 비연속 메모리 할당 방식을 사용하여 프로그램의 메모리 관리를 효율적으로 수행한다.

### 페이징이란?

### 페이지와 프레임

![image](https://hackmd.io/_uploads/ByJmvFNCT.png)

- 가상 메모리를 사용하는 컴퓨터 시스템의 메모리 관리 기법
  - 가상 메모리 : 프로그램이 사용하는 메모리 공간을 물리적 메모리보다 크게 설정하는 것
- 이 방식에서, 물리적 메모리는 `페이지`라고 불리는 고정 크기의 블록으로 나누어지며, 가상 메모리는 `프레임`이라고 불리는 물리적 페이지와 일치하는 크기의 블록으로 나누어진다.
  - 페이지 : 프로세스의 논리 주소로 공간을 일정한 크기 단위로 자른 것
  - 프레임 : 메모리의 물리 주소 공간을 일정한 크기 단위로 자른 것
  - 페이지와 프레임은 동일한 크기로 설정되며, 이 크기 단위로 메모리 할당이 이루어진다

![image](https://hackmd.io/_uploads/H1P9OtE06.png)
![image](https://hackmd.io/_uploads/HklXKKVAp.png)

페이징의 핵심 아이디어는 모든 메모리 접근이 페이지를 통해 이루어진다는 것이다. 프로그램이 메모리에 접근하려 할 때, 가상 주소를 물리적 주소로 변환해야 하며, 이 과정에서 페이징 시스템이 중요한 역할을 한다.

페이징 기법의 주요 장점은 다음과 같다

- **단편화 방지:** 페이징은 외부 단편화 문제를 완전히 해결한다.
- **데이터 보호:** 각 프로세스의 메모리 영역이 분리되어 있어, 한 프로세스가 다른 프로세스의 메모리에 무단으로 접근하는 것을 방지한다.
- **유연성:** 프로그램을 물리적 메모리의 연속적인 영역에 로드할 필요가 없어, 메모리 관리가 더 유연해진다.

### 내부 단편화

![image](https://hackmd.io/_uploads/B1RkOYNCT.png)

- 페이징 시스템에서는 외부 단편화 문제가 해결되지만, 내부 단편화 문제가 발생할 수 있다.
- 내부 단편화는 페이지의 크기가 프로그램의 크기보다 큰 경우 발생한다.
- 그래도 외부 단편화보다는 훨씬 더 효율적이다.

### 페이징 테이블

![image](https://hackmd.io/_uploads/S1aQnF4AT.png)

- 페이징 시스템에서는 가상 주소를 물리적 주소로 변환하기 위해 페이징 테이블(또는 페이지 테이블)을 사용한다.
  - 페이지 테이블은 가상 페이지 번호(VPN)와 해당하는 물리적 페이지 번호(PPN)의 매핑을 저장한다.
- 페이지 테이블은 보통 메모리에 저장되며, 각 프로세스는 자신만의 페이지 테이블을 가진다.
- 운영 체제는 이 테이블을 관리하며, 프로세스가 메모리에 접근할 때마다 페이지 테이블을 참조하여 가상 주소를 물리적 주소로 변환한다.

### 페이징에서의 주소 변환

![image](https://hackmd.io/_uploads/HJlunF4AT.png)

페이징 시스템에서는 모든 논리 주소가 페이지 번호(page number)와 변위(offset)로 이루어져 있다.

- 페이지 번호: 접근하고자 하는 페이지 번호로 페이지 테이블에서 해당 페이지 번호를 찾으면 어떤 프레임에 할당되었는지 알 수 있다
- 변위: 접근하려는 주소가 프레임의 시작 번지로부터 얼만큼 떨어져 있는지를 알기 위한 정보
- 프레임 번호 : 페이지 번호에 대한 물리적 주소

페이징 시스템에서의 주소 변환 과정은 다음과 같이 진행된다

1. 논리 주소가 페이지 번호와 변위로 나뉜다
2. 페이지 번호를 통해 페이지 테이블에서 해당 페이지 번호에 대한 프레임 번호를 찾는다
3. 프레임 번호와 변위를 결합하여 물리적 주소를 얻는다
4. 이 물리적 주소를 통해 실제 메모리에 접근한다

이 과정은 모든 메모리 접근 시에 자동으로 이루어지며, 프로그램은 이 과정을 명시적으로 제어할 수 없다.

### 페이지 테이블 엔트리

![image](https://hackmd.io/_uploads/B1Jm6FERa.png)

페이지 테이블 엔트리(PTE: Page Table Entry)는 페이지 테이블 내에서 하나의 항목을 의미한다. 각 엔트리는 물리적 페이지 번호와 함께 여러 제어 비트를 포함한다. 제어 비트에는 다음과 같은 정보가 포함될 수 있다

![image](https://hackmd.io/_uploads/HkBP6F4Ca.png)

- **유효 비트(Valid Bit):** 해당 페이지가 메모리에 있는지를 나타낸다.
- **보호 비트(Protection Bits):** 페이지에 대한 접근 권한(읽기, 쓰기, 실행)을 나타낸다.
- **변경 비트(Dirty Bit):** 페이지가 수정되었는지를 나타낸다.
- **참조 비트(Reference Bit):** 페이지가 최근에 참조되었는지를 나타낸다.

페이지 테이블 엔트리는 메모리 접근 제어와 관련된 중요한 정보를 제공하며, 운영 체제는 이 정보를 사용하여 메모리 보호와 프로세스 간 통신을 관리한다.

## 페이지 교체와 프레임 할당

![image](https://hackmd.io/_uploads/rykT6tVA6.png)

메모리 관리에서 페이징은 중요한 역할을 한다. 그러나 모든 페이지를 물리적 메모리에 동시에 유지할 수 없을 때, 운영 체제는 어떤 페이지를 메모리에 유지할지 결정해야 한다. 이때 필요한 기법이 바로 '페이지 교체'이다.

### 요구 페이지 (Paging on Demand)

- 요구 페이지 : 프로그램 실행 과정에서 필요할 때만 메모리로 불러오는 방식
  - 메모리 사용의 효율성을 높이는 방법이다.
- 페이지 폴트 : 요구 페이지 방식에서, 프로그램이 실행되는 동안 필요한 페이지가 메모리에 없을 때 발생하는 상황
  - 페이지 폴트가 발생하면, 운영 체제는 해당 페이지를 디스크에서 메모리로 불러와야 한다.
- 요구 페이지 기법의 핵심은 '지역성의 원리(Locality of Reference)'에 기반한다.
  - 프로그램은 특정 시간에 특정 부분의 코드와 데이터만을 주로 사용하는 경향이 있다.
  - 이 원리를 이용하여, 현재 활성화되어 사용되는 부분의 페이지만을 메모리에 유지함으로써, 메모리 사용을 최적화할 수 있다.

### 페이지 교체 알고리즘

요구 페이징 기법을 사용하다보면 메모리가 가득 차게 되어 스왑 아웃을 해야하는 경우가 발생한다. 이때 어떤 페이지를 교체할지 결정하는 것이 페이지 교체 알고리즘이다.
여러 페이지 교체 알고리즘이 있으며, 각각의 성능과 복잡성은 다르다. 일반적으로 페이지 폴트를 최소화하고, 페이지 교체의 비용을 최소화하는 것이 목표이다.

#### FIFO (First-In, First-Out)

![image](https://hackmd.io/_uploads/B15lk9ER6.png)

- 가장 오래 전에 메모리에 적재된 페이지를 교체한다.
- FIFO는 이해하고 구현하기 쉬우나, 오래된 페이지가 여전히 활발히 사용될 수 있다는 단점이 있다.

#### OPT (Optimal Page Replacement)

![image](https://hackmd.io/_uploads/BkZrJqERa.png)

- OPT 알고리즘은 미래에 가장 오랫동안 사용되지 않을 페이지를 교체한다.
- 이론적으로 가장 효율적인 방법이지만, 미래의 메모리 접근 패턴을 예측할 수 없기 때문에 실제로는 구현할 수 없다.

#### LRU (Least Recently Used)

![image](https://hackmd.io/_uploads/rJRrk94Cp.png)

- LRU 알고리즘은 가장 오랫동안 사용되지 않은 페이지를 교체한다.
- 이 방법은 프로그램의 지역성 원리를 잘 반영하지만, 구현이 복잡하고 비용이 많이 든다.

### 계층적 페이징

![image](https://hackmd.io/_uploads/HkVPb5406.png)

- 계층적 페이징은 페이지 테이블을 계층적으로 구성하여 메모리 사용을 최적화하는 방법이다.
- 계층적 페이징은 페이지 테이블을 여러 수준으로 나누어 관리함으로써, 페이지 테이블의 크기를 줄이고, 메모리 사용을 최적화한다.
- 계층적 페이징은 페이지 테이블의 크기를 줄이는 장점이 있지만, 페이지 테이블의 접근 시간이 증가할 수 있다는 단점이 있다.

![image](https://hackmd.io/_uploads/ry2v-9V06.png)

### 스래싱과 프레임 할당

![image](https://hackmd.io/_uploads/r1w0yqECa.png)

프레임의 수가 적은 경우에도 페이지 폴트가 자주 발생한다.

![image](https://hackmd.io/_uploads/rJfAJq4Ap.png)

페이지 폴트가 과해지면 프로세스 실행 시간보다 페이지 교체에 더 많은 시간을 소비하게 되는데, 이를 '스래싱'이라고 한다. 스래싱의 근본적인 원인은 각 프로세스가 필요로 하는 최소한의 프레임을 할당받지 못했기 때문이다.

![image](https://hackmd.io/_uploads/SyXRlqEAa.png)

스래싱을 방지하기 위한 한 가지 방법은 적절한 프레임 할당이다. 각 프로세스에 충분한 수의 프레임을 할당하여, 페이지 교체 빈도를 줄이고, 시스템의 성능을 유지해야 한다.

프레임 할당 기법에는 고정 할당(각 프로세스에 고정된 수의 프레임 할당)과 가변 할당(사용 패턴에 따라 프레임 수를 조정)이 있다.

#### 정적 할당 (Static Allocation)

프로세스의 실행과정은 고려하지 않고 단순히 프로세스 크기와 물리적인 메모리의 크기만 고려하여 프레임을 할당하는 방식이다. 균등 분배, 비례 분배 등의 방식이 있다.

| 균등 분배 | 비례 분배 |
| :---: | :---: |
| 모든 프로세스에 동일한 수의 프레임을 할당하는 방식 | 프로세스의 크기에 따라 프레임을 할당하는 방식 |
|![image](https://hackmd.io/_uploads/r1RTbcN06.png)|![image](https://hackmd.io/_uploads/Hy11f94CT.png)|

> 정적 할당 방식은 프로세스를 실행하는 초기에 프레임을 할당하기 때문에 프로세스를 실행하는 동안 메모리 요구를 반영하지 못하는 단점이 있다.

#### 동적 할당 (Dynamic Allocation)

프로세스의 실행과정을 고려하여 적절한 프레임 수를 할당하는 방식이다. 동적 할당 방식은 프로세스의 실행 패턴을 고려하여 프레임을 할당하기 때문에 스래싱을 방지할 수 있다. 크게 '작업 집합'과 '페이지 부재율'을 기반으로 프레임을 할당하는 방식이 있다.

| 작업 집합 | 페이지 부재율 |
| :---: | :---: |
| 최근 일정 시간 동안 참조된 페이지들의 집합을 기반으로 프레임을 할당하는 방식 | 페이지 부재율을 기반으로 프레임을 할당하는 방식 |
| ![image](https://hackmd.io/_uploads/SJLif54C6.png) | ![image](https://hackmd.io/_uploads/BJz0QqN06.png) |
