이전에 프로세스의 메모리 구조와 메모리 계층 구조를 정리하면서
프로그램이 메모리를 어떤 구조로 사용하고, CPU가 메모리에 어떻게 접근하는지에 대해 정리했었다.
이번에는 여기서 더 나아가 운영체제가 메모리 공간을 어떤 방식으로 관리하는지 정리해보려고 한다.
프로그램이 메모리를 사용하려면 운영체제로부터 메모리 공간을 할당받아야 한다.
하지만 메모리를 계속 할당하고 해제하다 보면 메모리 공간이 남아 있어도 효율적으로 사용하지 못하는 상황이 생길 수 있다.
이런 문제가 메모리 단편화이다.
운영체제는 이런 문제를 줄이기 위해 페이징 같은 메모리 관리 방식을 사용한다.
이번 글에서는 메모리 단편화가 무엇인지, 페이징과 세그멘테이션은 어떤 방식인지,
그리고 페이징과 함께 자주 나오는 페이지 폴트까지 정리해보려고 한다.
메모리 단편화란?
메모리 단편화는 메모리 공간이 남아 있지만,
빈 공간이 흩어져 있거나 할당된 공간 내부에 낭비가 생겨서 메모리가 비효율적으로 사용되는 현상이다.
즉, 전체적으로 보면 메모리가 남아 있는 것 같지만,
실제로는 원하는 크기의 메모리를 제대로 할당하지 못하거나 할당받은 공간 일부가 사용되지 않고 낭비될 수 있다.
메모리 단편화는 크게 두 가지로 나눌 수 있다.
- 내부 단편화
- 외부 단편화
내부 단편화
내부 단편화는 실제로 필요한 크기보다 더 큰 메모리를 할당받아 할당된 공간 내부에서 메모리가 낭비되는 현상이다.
예를 들어 메모리를 10MB 단위로 관리한다고 해보자.
어떤 프로그램이 실제로 필요한 메모리는 6MB인데 관리 단위 때문에 10MB를 할당받는다면
나머지 4MB는 사용되지 않고 낭비된다.
이처럼 할당받은 메모리 블록 안에서 사용하지 않는 공간이 생기는 문제가 내부 단편화이다.
외부 단편화
외부 단편화는 여유 메모리 공간이 잘게 흩어져 있어서
전체 여유 공간은 충분하지만 큰 연속된 공간을 할당하지 못하는 문제이다.
예를 들어 메모리 상태가 다음과 같다고 해보자.
[사용 중][빈 2KB][사용 중][빈 8KB][사용 중][빈 5KB]
이 경우 빈 공간의 총합은 15KB이다.
하지만 빈 공간들이 서로 떨어져 있기 때문에 10KB의 연속된 메모리 공간을 할당할 수 없다.
이런 문제가 외부 단편화이다.
외부 단편화는 가변 크기 메모리 블록의 할당과 해제를 반복할 때 발생하기 쉽다.
메모리 단편화를 해결하는 방법
메모리 단편화를 해결하거나 줄이기 위한 방법에는 다음과 같은 방식이 있다.
- 압축
- 페이징
- 세그멘테이션
압축
압축은 흩어져 있는 빈 공간을 하나로 모으기 위해 사용 중인 메모리 블록들을 한쪽으로 이동시키는 방식이다.
사용 중인 메모리들을 한쪽으로 모으면 떨어져 있던 빈 공간을 하나의 큰 연속된 공간으로 만들 수 있다.
따라서 외부 단편화를 해결할 수 있다.
하지만 단점도 크다.
실행 중인 메모리 블록을 이동해야 하므로 비용이 크고 주소 정보도 함께 갱신해야 한다.
또한 실행 중인 프로그램의 객체나 메모리 위치를 런타임에 마음대로 옮기는 것은 쉽지 않다.
그래서 개념적으로는 외부 단편화를 해결할 수 있지만 실제로는 비용이 큰 방식이라고 볼 수 있다.
페이징
페이징은 메모리를 작은 고정 크기 단위로 나누어 관리하는 방식이다.
가상 메모리에서는 이 고정 크기 블록을 페이지라고 부르고,
물리 메모리에서는 같은 크기의 블록을 프레임이라고 부른다.
보통 페이지와 프레임은 같은 크기를 가지며 일반적으로 4KB 단위로 관리되는 경우가 많다.
페이징을 사용하면 프로세스 입장에서는 연속된 가상 주소 공간을 사용하는 것처럼 보인다.
하지만 실제 물리 메모리에서는 각 페이지가 서로 떨어진 프레임에 매핑될 수 있다.
개념적으로는 다음과 같이 볼 수 있다.
가상 메모리: [Page 0][Page 1][Page 2][Page 3]
매핑 관계:
Page 0 → Frame 5
Page 1 → Frame 1
Page 2 → Frame 9
Page 3 → Frame 2
즉, 가상 주소는 연속되어 있어도 물리 메모리에서는 반드시 연속되어 있을 필요가 없다.
이 덕분에 물리 메모리의 외부 단편화를 크게 줄일 수 있다.
다만 페이지는 고정 크기 단위로 할당되기 때문에 페이지 크기보다 작은 남는 공간이 생길 수 있다.
예를 들어 페이지 크기가 4KB인데 5KB가 필요하다면 4KB 페이지 2개가 필요하다.
이 경우 총 8KB를 할당받게 되고, 실제로는 5KB만 사용하므로 3KB가 낭비된다.
다시 말해, 페이징은 외부 단편화를 줄이는 장점이 있지만,
페이지 단위보다 작은 낭비로 인해 내부 단편화가 발생할 수 있다.
페이지 테이블과 TLB
페이징을 사용하면 가상 주소를 실제 물리 주소로 변환해야 한다.
이때 사용하는 자료구조가 페이지 테이블이다.
페이지 테이블은 가상 페이지가 어떤 물리 프레임에 매핑되어 있는지 저장한다.
CPU가 메모리에 접근할 때는 가상 주소를 물리 주소로 변환해야 한다.
이 과정에서 페이지 테이블을 참조한다.
하지만 매번 페이지 테이블을 확인하면 비용이 커질 수 있다.
그래서 자주 사용되는 주소 변환 결과는 TLB라는 캐시에 저장해두고 사용한다.
즉, TLB는 가상 주소에서 물리 주소로 변환한 결과를 저장하는 캐시라고 볼 수 있다.
세그멘테이션
세그멘테이션은 메모리를 의미 있는 단위로 나누어 관리하는 방식이다.
예를 들어 프로그램의 메모리 구조를 다음과 같이 나누는 방식이다.
- Code
- Data
- Heap
- Stack
페이징이 고정 크기 단위로 메모리를 나누는 방식이라면,
세그멘테이션은 프로그램의 논리적인 단위에 맞게 가변 크기의 세그먼트로 나누는 방식이다.
세그멘테이션은 필요한 크기만큼 세그먼트를 만들 수 있기 때문에 내부 단편화를 줄일 수 있다.
또한 코드 영역, 데이터 영역, 스택 영역처럼 의미 있는 단위로 나뉘기 때문에
각 영역에 보호나 공유 정책을 적용하기 쉽다.
하지만 세그먼트는 가변 크기 블록이므로 할당과 해제를 반복하면 외부 단편화가 발생할 수 있다.
페이징과 세그멘테이션 비교
페이징과 세그멘테이션을 비교하면 다음과 같다.
| 구분 | 페이징 | 세그멘테이션 |
|---|---|---|
| 관리 단위 | 고정 크기 페이지 | 의미 있는 가변 크기 세그먼트 |
| 기준 | 메모리 관리 편의성 | 프로그램의 논리 구조 |
| 장점 | 외부 단편화 감소 | 내부 단편화 감소, 보호/공유 적용 쉬움 |
| 단점 | 내부 단편화 발생 가능 | 외부 단편화 발생 가능 |
페이징은 물리 메모리를 효율적으로 관리하기 위한 방식에 가깝고,
세그멘테이션은 프로그램의 논리 구조를 반영하기 좋은 방식이라고 볼 수 있다.
페이지 폴트란?
페이지 폴트는 프로그램이 가상 메모리의 데이터에 접근하려 할 때,
해당 데이터가 물리 RAM에 없는 경우 발생하는 예외 상황이다.
페이지 폴트는 MMU(Memory Management Unit)가 감지하고 운영체제가 필요한 처리를 수행한다.
페이지 폴트라고 하면 무조건 오류처럼 느껴질 수 있지만 항상 잘못된 상황을 의미하는 것은 아니다.
운영체제의 메모리 관리 과정에서 자연스럽게 발생하는 페이지 폴트도 있고,
잘못된 주소 접근이나 권한 위반처럼 오류에 해당하는 페이지 폴트도 있다.
페이지 폴트의 종류
페이지 폴트는 크게 다음과 같이 나눌 수 있다.
- Minor 페이지 폴트
- Major 페이지 폴트
- Invalid 페이지 폴트
Minor 페이지 폴트
Minor 페이지 폴트는 필요한 데이터가 이미 RAM에 있지만,
현재 프로세스가 바로 접근할 수 있도록 매핑 정보가 준비되지 않은 경우 발생한다.
이 경우 디스크에서 데이터를 읽어올 필요는 없고 운영체제가 매핑 정보만 갱신하면 접근할 수 있다.
Minor 페이지 폴트는 운영체제의 메모리 관리 과정에서 자연스럽게 발생할 수 있는 페이지 폴트라고 볼 수 있다.
Major 페이지 폴트
Major 페이지 폴트는 필요한 데이터가 RAM에 없어서 디스크에서 데이터를 가져와야 하는 경우이다.
디스크 접근은 RAM 접근보다 훨씬 느리기 때문에 Major 페이지 폴트는 성능에 더 큰 영향을 줄 수 있다.
예를 들어 RAM이 부족해서 어떤 페이지가 디스크로 내려간 상태에서
그 페이지에 다시 접근하면 Major 페이지 폴트가 발생할 수 있다.
운영체제는 디스크에서 해당 데이터를 다시 읽어와 RAM에 올린 뒤 프로그램이 계속 실행될 수 있도록 처리한다.
Major 페이지 폴트 또한 운영체제의 메모리 관리 과정에서 발생할 수 있는 자연스러운 페이지 폴트이지만,
디스크 접근이 필요하기 때문에 Minor 페이지 폴트에 비해 성능 비용은 더 크다.
Invalid 페이지 폴트
Invalid 페이지 폴트는 잘못된 주소 접근이나 권한 위반처럼 정상적으로 복구할 수 없는 페이지 폴트이다.
예를 들어 다음과 같은 상황이 있다.
nullptr에 접근하는 경우- 해제된 메모리에 접근하는 경우
- 읽기 전용 페이지에 쓰려고 하는 경우
이런 경우는 정상적인 페이지를 가져와서 복구할 수 있는 상황이 아니다.
따라서 프로그램 오류로 이어질 수 있는 오류성 페이지 폴트이다.
페이지 폴트가 발생하는 상황
페이지 폴트가 발생하는 대표적인 상황은 다음과 같다.
- RAM에 올라오지 않은 페이지에 접근할 때
- 디스크로 내려간 페이지에 다시 접근할 때
- 실행 파일이나 DLL의 코드 / 데이터를 처음 사용할 때
- 잘못된 주소에 접근할 때
- 권한이 없는 방식으로 접근할 때
RAM에 올라오지 않은 페이지에 접근할 때
프로그램이 큰 데이터를 할당할 때 운영체제는 처음부터 모든 물리 메모리를 바로 할당하지 않을 수 있다.
가상 주소 공간만 예약해두고 실제로 해당 메모리에 접근하는 순간 물리 페이지를 할당할 수 있다.
이때 페이지 폴트가 발생하고 운영체제가 필요한 물리 페이지를 할당한다.
이런 경우는 Demand-Zero fault에 해당하며 Minor 페이지 폴트에 가깝게 볼 수 있다.
디스크로 내려간 페이지에 다시 접근할 때
RAM에 있던 페이지를 오랫동안 사용하지 않거나 RAM이 부족해지면,
운영체제는 해당 페이지를 디스크 영역으로 내릴 수 있다.
이후 프로그램이 그 페이지에 다시 접근하면 해당 페이지는 RAM에 없는 상태이므로 페이지 폴트가 발생한다.
운영체제는 디스크에서 해당 페이지를 다시 읽어와 RAM에 올린 뒤 접근을 계속할 수 있게 한다.
이 경우는 Major 페이지 폴트에 해당한다.
실행 파일이나 DLL을 처음 사용할 때
실행 파일이나 DLL의 코드와 데이터는 프로그램 시작 시점에 전부 RAM에 올라오지 않을 수 있다.
운영체제는 필요한 부분만 메모리에 올리는 요구 페이징 방식을 사용할 수 있다.
따라서 어떤 코드나 데이터가 처음 사용될 때 페이지 폴트가 발생하고, 그때 필요한 부분이 메모리에 로드될 수 있다.
만약 해당 코드나 데이터를 디스크에서 읽어야 한다면 Major 페이지 폴트가 될 수 있고,
다른 프로세스가 같은 DLL 페이지를 사용하고 있어 이미 RAM에 있다면 Minor 페이지 폴트가 될 수 있다.
잘못된 주소에 접근할 때
잘못된 주소에 접근하면 Invalid 페이지 폴트가 발생할 수 있다.
예를 들어 nullptr을 역참조하거나 이미 해제된 메모리에 접근하는 경우가 있다.
이런 경우는 운영체제가 정상 페이지를 가져와서 복구할 수 있는 상황이 아니다.
따라서 프로그램 오류로 이어질 수 있다.
권한이 없는 방식으로 접근할 때
메모리 페이지에는 접근 권한이 설정될 수 있다.
예를 들어 읽기 전용 페이지에 쓰려고 하면 권한 위반으로 Invalid 페이지 폴트가 발생할 수 있다.
이 경우도 정상적으로 복구 가능한 페이지 폴트가 아니라 오류 상황으로 볼 수 있다.
정리
메모리 단편화는 메모리 공간이 남아 있어도 효율적으로 사용하지 못하는 현상이다.
내부 단편화는 할당받은 공간 내부에서 낭비가 발생하는 문제이고,
외부 단편화는 빈 공간이 흩어져 있어 큰 연속 공간을 할당하지 못하는 문제이다.
외부 단편화를 줄이기 위한 방식으로는 압축과 페이징이 있다.
압축은 흩어진 빈 공간을 하나로 모을 수 있지만 사용 중인 메모리를 이동해야 하므로 비용이 크다.
페이징은 가상 메모리를 페이지, 물리 메모리를 프레임이라는 고정 크기 단위로 나누어 관리한다.
프로세스 입장에서는 연속된 가상 주소를 사용하는 것처럼 보이지만,
실제 물리 메모리에서는 흩어진 프레임에 매핑될 수 있다.
이를 통해 외부 단편화를 줄일 수 있지만 페이지 단위보다 작은 낭비가 생기는 내부 단편화는 발생할 수 있다.
세그멘테이션은 Code, Data, Heap, Stack처럼 의미 있는 단위로 메모리를 나누는 방식이다.
프로그램의 논리 구조와 잘 맞고 내부 단편화를 줄일 수 있지만,
가변 크기 블록을 사용하므로 외부 단편화가 발생할 수 있다.
페이지 폴트는 가상 메모리의 데이터에 접근하려 할 때
해당 데이터가 물리 RAM에 없거나 접근할 수 없는 경우 발생하는 예외 상황이다.
Minor / Major 페이지 폴트처럼 운영체제가 정상적으로 처리할 수 있는 경우도 있고,
Invalid 페이지 폴트처럼 잘못된 주소 접근이나 권한 위반으로 발생하는 오류 상황도 있다.
마무리
이번에 메모리 단편화, 페이징, 페이지 폴트를 정리하면서
이 개념들이 모두 RAM을 어떻게 효율적으로 사용할 것인지와 연결된다는 것을 알게 되었다.
최근에는 PC의 RAM 용량이 커져서 일반적인 환경에서는 메모리 단편화나 페이지 폴트를 크게 체감하지 못할 수도 있다.
하지만 RAM이 제한된 환경이나 메모리를 많이 사용하는 프로그램을 고려한다면
이런 문제들을 반드시 신경 써야 한다고 생각한다.
특히 메모리 단편화는 남아 있는 메모리를 효율적으로 사용하지 못하게 만들 수 있고,
페이지 폴트는 필요한 데이터가 RAM에 없는 상황에서 발생한다.
결국 둘 다 RAM을 어떻게 사용하고 관리하는지와 밀접하게 관련되어 있기 때문에
RAM이 제한된 환경이나 메모리 사용량이 중요한 상황에서는 반드시 고려해야 한다고 생각한다.
또한 처음에는 페이지 폴트라는 이름 때문에 무조건 잘못된 접근이나 오류 상황이라고 생각했다.
하지만 공부해보니 운영체제가 필요한 페이지를 RAM에 올리는 과정에서 자연스럽게 발생하는 페이지 폴트도 있고,
잘못된 주소 접근이나 권한 위반처럼 실제 오류에 해당하는 페이지 폴트도 있다는 것을 알 수 있었다.
'C++, CS' 카테고리의 다른 글
| [Network] 방화벽이란? 트래픽 검사와 접근 제어 정리 (0) | 2026.06.04 |
|---|---|
| [Network] TCP와 UDP 차이, Socket 통신 흐름 정리 (0) | 2026.06.03 |
| [CS] 컴퓨터 메모리 계층 구조와 CPU 캐시 정리 (0) | 2026.06.01 |
| [CS] 프로세스 간 통신 방법과 Race Condition (1) | 2026.05.14 |
| [CS] 프로세스와 스레드의 차이, Context Switching 정리 (0) | 2026.05.12 |