테마
Chapter 05. 메모리 관리와 보안
운영체제가 **물리 메모리(Physical Memory)**를 어떻게 관리하는지, **가상 메모리(Virtual Memory)**가 왜 필요한지, 그리고 메모리 보호 메커니즘이 시스템 **보안(Security)**과 어떻게 연결되는지를 학습한다. 페이징(Paging), 세그멘테이션(Segmentation), 스왑(Swap), DEP(Data Execution Prevention) 등 핵심 개념을 다룬다.
5.1 물리 메모리와 주소 체계
메모리의 기본 단위: 바이트(Byte)와 주소(Address)
물리 메모리(RAM)는 1바이트(Byte) 단위로 쪼개져 있고, 각 바이트마다 **고유한 주소(일련번호)**가 붙어 있다.
비유하자면 워터파크 신발장과 같다. 신발장에는 1번, 2번, 3번... 이렇게 번호가 붙어 있고, 각 칸에 신발 한 켤레를 넣을 수 있다. 메모리도 마찬가지로 각 바이트마다 0번, 1번, 2번... 이라는 주소가 붙어 있고, 그 주소를 통해 데이터를 읽고 쓴다.
32비트 시스템 vs 64비트 시스템
CPU가 한 번에 처리할 수 있는 **주소의 크기(비트 수)**가 인식 가능한 메모리의 최대량을 결정한다.
32비트 시스템
- 주소가 32비트 숫자로 표현됨
- 2^32 = 4,294,967,296 바이트 = 약 4GB까지만 인식 가능
- 8GB RAM을 장착하고 32비트 OS를 설치하면 → 4GB만 사용, 나머지 4GB는 완전히 낭비됨
64비트 시스템
- 주소가 64비트 숫자로 표현됨
- 2^64 = 16 엑사바이트(EB) 이론상 가능 (사실상 무한에 가까움)
- 실제로는 OS가 제한을 둠:
| OS 에디션 | 최대 인식 RAM |
|---|---|
| Windows 11 Home | 128 GB |
| Windows 11 Pro | 2 TB |
| Windows 11 Enterprise | 6 TB |
| Windows Server | 64 TB |
| Linux (일반적) | 4 PB ~ 128 PB (커널 설정에 따라) |
64비트 플랫폼 = 64비트 CPU + 64비트 OS. 둘 중 하나라도 32비트이면 32비트로 동작한다.
데이터 크기 단위 체계
| 단위 | 영어 | 크기 |
|---|---|---|
| 바이트 | Byte (B) | 1 B |
| 킬로바이트 | Kilobyte (KB) | 1,024 B |
| 메가바이트 | Megabyte (MB) | 1,024 KB |
| 기가바이트 | Gigabyte (GB) | 1,024 MB |
| 테라바이트 | Terabyte (TB) | 1,024 GB |
| 페타바이트 | Petabyte (PB) | 1,024 TB |
| 엑사바이트 | Exabyte (EB) | 1,024 PB |
| 제타바이트 | Zettabyte (ZB) | 1,024 EB |
| 요타바이트 | Yottabyte (YB) | 1,024 ZB |
메모리의 두 종류
| 구분 | 명칭 | 예시 | 특성 |
|---|---|---|---|
| 1차 메모리 (Main Memory) | RAM | DDR4, DDR5 | 빠르지만 전원 꺼지면 데이터 소실 (휘발성) |
| 2차 메모리 (Secondary Storage) | 보조기억장치 | SSD, HDD | 느리지만 전원 꺼져도 데이터 유지 (비휘발성) |
CPU는 1차 메모리(RAM)에 있는 데이터만 직접 처리할 수 있다. 2차 메모리에 있는 데이터는 반드시 RAM으로 먼저 옮긴 뒤에야 CPU가 접근할 수 있다.
5.2 메모리 할당 방식과 단편화
MMU (Memory Management Unit)
**MMU(메모리 관리 장치)**는 하드웨어 수준에서 메모리를 관리하는 장치로, OS의 메모리 관리자 역할을 수행한다. 프로세스를 메모리 어디에 **배치(Placement)**할 것인지, 필요 시 어떻게 **재배치(Replacement)**할 것인지를 결정한다.
메모리에 프로세스를 배치하는 방식은 크게 가변 분할 방식과 고정 분할 방식 두 가지가 있다.
가변 분할 방식 (Variable Partition)
프로세스의 실제 크기에 맞게 연속된 메모리 공간을 할당하는 방식이다.
| 항목 | 설명 |
|---|---|
| 원리 | 10MB 프로세스 → 10MB 공간 할당, 25MB 프로세스 → 25MB 공간 할당 |
| 장점 | 프로세스 크기에 딱 맞게 배치하므로 빈 공간이 없어 촘촘하게 채울 수 있음 |
| 단점 | 프로세스가 종료되면 중간에 빈 구멍이 생김 → 외부 단편화(External Fragmentation) |
외부 단편화란?
프로세스들이 종료되면서 메모리 곳곳에 다양한 크기의 빈 공간이 흩어져 생긴다. 각각의 빈 공간은 작아서 새 프로세스를 넣기 어렵지만, 합치면 충분한 크기가 되는 상황이다.
**세그멘테이션(Segmentation)**은 가변 분할 방식의 대표적인 구현으로, 프로세스를 코드(Code), 데이터(Data), 스택(Stack) 등 논리적 의미 단위로 나누어 각각을 서로 다른 크기의 메모리 영역에 배치한다.
고정 분할 방식 (Fixed Partition)
메모리를 **일정한 크기(페이지)**로 미리 나누어 놓고, 프로세스를 이 페이지 단위로 할당하는 방식이다.
| 항목 | 설명 |
|---|---|
| 원리 | 메모리를 4KB 단위로 나눔 → 프로세스가 10KB이면 4KB 페이지 3개(12KB) 할당 |
| 장점 | 관리 로직이 단순하고 구현이 쉬움 |
| 단점 | 프로세스가 페이지보다 작으면 남는 공간 발생 → 내부 단편화(Internal Fragmentation) |
내부 단편화란?
10KB 프로세스에 4KB 페이지 3개(12KB)를 할당하면, 2KB가 남지만 다른 프로세스가 사용할 수 없는 낭비 공간이 된다. 이 공간은 할당된 블록 내부에 있으므로 내부 단편화라고 부른다.
**페이징(Paging)**은 고정 분할 방식의 대표적인 구현으로, 메모리를 **같은 크기(보통 4KB)**로 잘라서 관리한다.
현대 OS: 가변 + 고정 혼합 사용
현대 운영체제는 **페이징(고정 분할)**을 기본으로 사용하면서, 논리적 구분을 위해 **세그멘테이션(가변 분할)**도 함께 사용하는 혼합 방식을 채택한다. 이를 **세그멘티드 페이징(Segmented Paging)**이라 부른다.
스왑 (Swap)
RAM이 부족할 때, OS는 보조기억장치(SSD, HDD)의 일부를 마치 메모리처럼 사용한다. 이를 **스왑(Swap)**이라 한다.
| 동작 | 방향 | 설명 |
|---|---|---|
| 스왑 아웃 (Swap Out) | RAM → 보조기억장치 | 현재 안 쓰고 있는 프로세스를 내보내기 |
| 스왑 인 (Swap In) | 보조기억장치 → RAM | 필요한 프로세스를 다시 불러오기 |
페이지 단위로 이루어지면 Page Out / Page In이라고도 부른다.
SSD가 HDD보다 체감 성능이 압도적인 이유
Swap In/Out은 보조기억장치의 읽기/쓰기 속도에 직결된다. HDD는 디스크 회전과 헤드 이동이라는 기계적 동작이 필요하지만, SSD는 전기 신호로 바로 접근한다.
| 항목 | HDD | SSD |
|---|---|---|
| 랜덤 읽기 속도 | ~0.5 MB/s | ~500 MB/s |
| Swap In/Out 속도 | 매우 느림 | 빠름 |
| 체감 | 램 부족 시 시스템 멈춤 | 램 부족해도 버틸 만함 |
RAM이 부족해서 Swap이 자주 발생하는 상황에서, SSD는 HDD 대비 수백 배 빠른 속도로 데이터를 주고받기 때문에 체감 성능 차이가 극명하게 드러난다.
최대 절전 모드 (Hibernation)
노트북의 최대 절전 모드는 Swap의 극단적인 형태이다. RAM 전체 내용을 통째로 보조기억장치에 저장한 뒤 전원을 완전히 끈다. 다시 켜면 저장된 RAM 상태를 복원하여 꺼지기 직전의 상태 그대로 돌아올 수 있다.
| 모드 | RAM | 전원 | 복귀 속도 |
|---|---|---|---|
| 절전 모드 (Sleep) | 유지 (전력 공급 중) | 최소 전력 | 즉시 (1~2초) |
| 최대 절전 (Hibernation) | 디스크에 저장 → 전원 차단 | 완전 OFF | 느림 (10~30초) |
조각 모음 (Defragmentation)
HDD에서 파일이 여러 조각으로 흩어져 저장되면 헤드가 여기저기 움직여야 하므로 느려진다. 조각 모음은 이 조각들을 연속된 공간으로 모아주는 작업이다.
그런데 SSD는 기계적 헤드가 없으므로 조각 모음이 거의 불필요하다. 오히려 SSD에 조각 모음을 하면 불필요한 쓰기가 발생해 수명만 줄어든다.
5.3 가상 메모리 (Virtual Memory)
개념
**가상 메모리(Virtual Memory)**는 각 프로세스에게 독립적이고 연속적인 메모리 공간을 제공하는 기술이다. 실제 물리 메모리가 얼마든, 프로세스는 자기만의 넓고 깨끗한 메모리 공간을 가지고 있다고 착각한다.
가상 메모리의 세 가지 핵심 장점
| 장점 | 설명 | 예시 |
|---|---|---|
| 1. 하드웨어 독립성 | 물리 메모리 크기의 제약을 극복 | 2GB RAM인 PC에서도 4GB 가상 공간 사용 가능 |
| 2. 관리적 추상성 | OS가 메모리를 효율적으로 관리할 수 있는 추상 계층 제공 | 물리 메모리의 단편화를 프로세스가 신경 쓸 필요 없음 |
| 3. 접근 통제를 통한 보안 | 프로세스 간 메모리 격리 | 프로세스 A가 프로세스 B의 메모리를 볼 수 없음 |
32비트 기준 가상 주소 공간
32비트 시스템에서 각 프로세스는 4GB의 가상 주소 공간을 가진다. 이 공간은 두 영역으로 나뉜다.
| 영역 | 주소 범위 | 용도 |
|---|---|---|
| 사용자 모드 | 0x00000000 ~ 0x7FFFFFFF (하위 2GB) | 애플리케이션이 사용하는 코드, 데이터, 힙, 스택 |
| 커널 모드 | 0x80000000 ~ 0xFFFFFFFF (상위 2GB) | OS 커널이 사용하는 영역. 일반 프로그램은 접근 불가 |
모든 프로세스가 각각 4GB 가상 공간을 가지지만, 커널 영역(상위 2GB)은 모든 프로세스가 같은 물리 페이지를 공유한다. OS 커널은 하나이기 때문이다.
절대 주소 vs 상대 주소
| 구분 | 절대 주소 (Absolute Address) | 상대 주소 (Relative Address) |
|---|---|---|
| 정의 | 실제 물리 메모리의 고정된 번지 | 특정 기준점으로부터의 오프셋(떨어진 거리) |
| 특징 | 물리 메모리에서 유일한 위치를 가리킴 | 기준점이 바뀌면 가리키는 곳도 바뀜 |
| 예시 | 메모리 0x0040A000번지 | EBP 레지스터로부터 -8바이트 위치 |
스택에서의 상대 주소 활용
함수가 호출되면 **스택 프레임(Stack Frame)**이 만들어지고, 지역변수들은 ESP(스택 포인터) 또는 EBP(베이스 포인터) 레지스터를 기준으로 한 상대 주소로 접근한다.
int add(int a, int b) {
int result = a + b; // result는 EBP-4 위치에 저장
return result;
}여기서 result는 절대 주소가 아니라 EBP - 4라는 상대 주소로 접근한다. 함수가 메모리 어디에 적재되든 EBP 기준으로 찾기 때문에, 프로세스가 어디에 배치되든 상관없이 동작할 수 있다.
5.4 페이징(Paging)과 세그멘테이션(Segmentation)
페이지와 프레임
| 용어 | 대상 | 설명 |
|---|---|---|
| 페이지 (Page) | 가상 메모리 | 가상 메모리를 나눈 논리적 단위 |
| 프레임 (Frame) | 물리 메모리 | 물리 메모리를 나눈 물리적 단위 |
페이지와 프레임은 같은 크기(보통 4KB)이다. OS는 **페이지 테이블(Page Table)**이라는 매핑 테이블을 통해 가상 주소(페이지 번호)를 물리 주소(프레임 번호)로 변환한다. 이 과정을 **DAT(Dynamic Address Translation, 동적 주소 변환)**라고 한다.
주소 변환 과정
프로세스가 가상 주소에 접근하면 MMU가 다음 과정을 거쳐 물리 주소로 변환한다.
세그멘테이션 (Segmentation)
세그멘테이션은 메모리를 논리적 의미 단위로 나누는 방식이다.
| 세그먼트 | 내용 |
|---|---|
| 코드 세그먼트 (Code/Text) | 실행할 명령어 |
| 데이터 세그먼트 (Data) | 전역 변수, static 변수 |
| 스택 세그먼트 (Stack) | 지역 변수, 함수 호출 정보 |
| 힙 세그먼트 (Heap) | 동적으로 할당한 메모리 |
페이징은 기계적으로 같은 크기로 자르지만, 세그멘테이션은 의미 있는 단위로 자른다는 차이가 있다.
페이지 폴트 (Page Fault)
프로세스가 접근하려는 가상 주소에 매핑된 물리 메모리 프레임이 없을 때 발생하는 예외(Exception)이다.
정상적인 페이지 폴트
요청한 페이지가 디스크(스왑 영역)에 있는 경우, OS가 해당 페이지를 RAM으로 불러오고(Page In) 매핑을 갱신한 뒤 프로세스를 계속 실행한다. 이것은 가상 메모리의 정상적인 동작이다.
비정상적인 페이지 폴트 (프로그램 크래시)
잘못된 포인터가 유효하지 않은 가상 주소를 가리키면, 매핑 자체가 존재하지 않으므로 복구가 불가능하다. 이 경우 OS는 프로세스를 강제 종료한다.
int *ptr = NULL; // ptr은 주소 0x00000000을 가리킴
*ptr = 42; // 주소 0에 접근 → 매핑 없음 → 페이지 폴트 → 크래시!포인터 관련 버그의 대부분은 이 메커니즘으로 설명된다. 포인터가 잘못된 주소를 가리키면 → 매핑이 없거나 권한이 없음 → 페이지 폴트 → 프로그램 크래시(Segmentation Fault).
메모리 접근 권한
페이지 테이블의 각 항목에는 매핑 정보뿐 아니라 **접근 권한 비트(Permission Bits)**도 포함되어 있다.
| 권한 비트 | 의미 | 설명 |
|---|---|---|
| R (Read) | 읽기 | 해당 페이지의 데이터를 읽을 수 있음 |
| W (Write) | 쓰기 | 해당 페이지에 데이터를 쓸 수 있음 |
| X (Execute) | 실행 | 해당 페이지의 내용을 코드로 실행할 수 있음 |
| 메모리 영역 | 일반적 권한 | 이유 |
|---|---|---|
| 코드 (Code/Text) | R-X (읽기+실행) | 코드는 읽고 실행하지만 수정하면 안 됨 |
| 데이터 (Data) | RW- (읽기+쓰기) | 변수는 읽고 쓰지만 실행하면 안 됨 |
| 스택 (Stack) | RW- (읽기+쓰기) | 지역 변수 저장 용도. 실행 불가 |
| 힙 (Heap) | RW- (읽기+쓰기) | 동적 할당 영역. 실행 불가 |
허용되지 않은 접근을 시도하면 → Access Violation (접근 위반) 오류가 발생하고 프로세스가 종료된다.
DEP (Data Execution Prevention, 데이터 실행 방지)
DEP는 데이터 영역(스택, 힙)에서 코드 실행을 차단하는 보안 기능이다.
왜 필요한가?
해커들의 대표적 공격 기법인 **버퍼 오버플로우(Buffer Overflow)**를 방어하기 위해서이다.
| 공격 | 설명 | DEP 효과 |
|---|---|---|
| 버퍼 오버플로우 | 스택에 악성 코드를 주입 | 스택에서 실행 차단 → 공격 무력화 |
| RCE (Remote Code Execution) | 원격에서 서버 프로세스에 코드 주입 후 실행 | 데이터 영역 실행 차단 → 방어 |
DEP 덕분에 해커가 버퍼 오버플로우로 스택에 악성 코드를 넣더라도, 스택에는 실행 권한(X)이 없기 때문에 코드가 실행되지 않고 프로세스가 종료된다. 이것이 원격 코드 실행(RCE: Remote Code Execution) 공격을 방어하는 핵심 메커니즘이다.
5.5 프로세스와 권한 상속
권한 상속의 원리
사용자가 시스템에 로그인하면 다음 과정이 일어난다.
- 로그인 시스템이 사용자의 계정 정보(ID, 권한 등급)를 확인
- 해당 계정의 권한으로 쉘(Shell) 프로세스를 생성
- 쉘에서 실행하는 모든 프로그램(자식 프로세스)은 부모(쉘)의 권한을 상속 받음
해킹의 기본 원리: 권한 탈취
해킹의 많은 공격 기법은 이 권한 상속 구조를 악용한다.
공격 시나리오
시스템에서 **높은 권한(System/Root)**으로 실행되는 프로세스(예: 웹 서버, DB 서버)의 취약점을 이용하여, 해당 프로세스를 통해 시스템 권한의 자식 프로세스를 생성하는 것이다.
방어 원칙
| 원칙 | 설명 |
|---|---|
| 최소 권한 원칙 (Least Privilege) | 프로세스에 필요한 최소한의 권한만 부여. 웹 서버가 System 권한으로 실행될 필요 없음 |
| DEP 활성화 | 데이터 영역에서 코드 실행 차단 (5.4절 참고) |
| ASLR (Address Space Layout Randomization) | 프로세스의 메모리 배치를 매번 랜덤화하여 공격자가 주소를 예측하기 어렵게 만듦 |
| 가상 메모리 격리 | 프로세스 간 메모리 접근을 차단하여 한 프로세스가 뚫려도 다른 프로세스에 영향 최소화 |
핵심 정리
주요 용어 정리
| 용어 | 영어 | 핵심 설명 |
|---|---|---|
| 물리 메모리 | Physical Memory | RAM. 바이트 단위로 주소가 부여된 실제 하드웨어 메모리 |
| 가상 메모리 | Virtual Memory | 프로세스에게 독립적이고 연속적인 메모리 공간을 제공하는 추상화 기술 |
| 페이지 | Page | 가상 메모리를 나눈 논리적 단위 (보통 4KB) |
| 프레임 | Frame | 물리 메모리를 나눈 물리적 단위 (페이지와 같은 크기) |
| 외부 단편화 | External Fragmentation | 가변 분할에서 프로세스 종료 후 빈 공간이 흩어져 생기는 낭비 |
| 내부 단편화 | Internal Fragmentation | 고정 분할에서 할당 블록 내부에 남는 사용 불가 공간 |
| 스왑 | Swap | RAM 부족 시 보조기억장치를 메모리처럼 사용하는 기법 |
| 페이지 폴트 | Page Fault | 가상 주소에 매핑된 물리 프레임이 없을 때 발생하는 예외 |
| 페이지 테이블 | Page Table | 가상 주소를 물리 주소로 변환하는 매핑 테이블 |
| DEP | Data Execution Prevention | 데이터 영역(스택, 힙)에서 코드 실행을 차단하는 보안 기능 |
| MMU | Memory Management Unit | 메모리 관리를 담당하는 하드웨어 장치 |
| 권한 상속 | Privilege Inheritance | 자식 프로세스가 부모 프로세스의 접근 권한을 물려받는 구조 |
5줄 요약
- 물리 메모리는 바이트 단위로 주소가 붙어 있으며, 32비트 시스템은 최대 4GB, 64비트 시스템은 이론상 16EB까지 인식할 수 있다.
- 메모리 할당은 **가변 분할(외부 단편화)**과 **고정 분할(내부 단편화)**의 트레이드오프이며, 현대 OS는 페이징과 세그멘테이션을 혼합하여 사용한다.
- 가상 메모리는 프로세스에게 독립적인 주소 공간을 제공하여 하드웨어 독립성, 관리 효율성, 보안 격리를 달성한다.
- 페이지 테이블이 가상 주소를 물리 주소로 변환하며, 매핑이 없으면 페이지 폴트가 발생한다 --- 포인터 버그로 인한 크래시의 핵심 원인이다.
- DEP와 메모리 접근 권한은 버퍼 오버플로우 및 원격 코드 실행(RCE) 공격을 차단하며, 최소 권한 원칙과 함께 시스템 보안의 기초를 이룬다.