가상 메모리

낚시하는 곰·2025년 3월 21일

krafton jungle

목록 보기
19/52

가상 메모리란?

실제 물리 메모리(RAM)의 한계를 극복하기 위해 운영체제가 만들어낸 논리적인 메모리 공간

  • 각 프로세스가 자신만의 독립된 주소 공간을 가지도록 만들어 줌
  • 실제로는 물리 메모리 + 디스크(페이지 파일) 를 조합해서 구성됨
  • 운영체제가 메모리 보호, 공간 분리, 메모리 확장을 가능하게 함

✅ 즉, 프로세스는 자기 메모리만 쓰는 것처럼 보이지만, 실제로는 운영체제가 배후에서 가상 주소 → 물리 주소로 매핑해서 처리하고 있어.

동작 흐름

  1. 프로그램 실행
  • 코드가 메모리로 로드되고, CPU가 명령어를 실행하기 시작함
  • 이때 CPU는 해당 명령어의 주소를 가상 주소로 본다
CPU: "0xB8000000 주소에서 명령어를 실행해야 해!" → 가상 주소
  1. MMU가 가상 주소를 물리 주소로 변환
    💡 MMU (Memory Management Unit)
  • CPU에 내장된 하드웨어 유닛
  • 가상 주소를 물리 주소로 바꾸는 장치
  • 운영체제가 제공한 페이지 테이블(Page Table) 을 참고해서 변환 수행
CPU → MMU → Page Table → 실제 물리 메모리 주소로 변환
  1. 페이지 테이블(Page Table)
    운영체제가 각 프로세스마다 만들어주는 가상 주소 ↔ 물리 주소 매핑 테이블
  • 가상 주소를 페이지 단위 (보통 4KB) 로 나누고
  • 각 가상 페이지가 어떤 물리 페이지에 매핑되는지 기록
[가상 주소 0x0000_1000] → [물리 주소 0xFFF0_0000]  
[가상 주소 0x0000_2000] → [디스크에 있음 → 페이지 폴트 발생]
  • CPU가 명령어를 실행하면서 참조하는 모든 주소는 가상 주소
  • 이걸 MMU가 페이지 테이블을 통해 물리 주소로 변환해서 RAM에 접근

예시로 이해하기

📌 상황

  • A라는 프로그램이 실행되고 있음
  • A는 0x00400000 주소(가상 주소)에 있는 함수를 호출함
  • CPU는 0x00400000을 실행하려고 함

📌 내부 동작

  • CPU가 0x00400000 주소를 MMU에 전달
  • MMU는 운영체제가 만든 페이지 테이블을 조회
  • 해당 가상 주소가 물리 주소 0x7FA00000에 매핑되어 있음을 확인
  • CPU는 0x7FA00000에서 명령어를 실행

CPU와 가상 주소의 깊은 연결

  1. 모든 명령어와 데이터 접근은 가상 주소 기준
  • 레지스터에 저장되는 주소, 스택 포인터, 명령어 포인터(PC) 등 전부 가상 주소
  • 함수 호출 시 스택 프레임도 가상 주소로 설정됨
  • 변수 접근, 배열 참조, 포인터 사용 모두 가상 주소 기준
  1. 컨텍스트 스위칭 시 페이지 테이블도 교체
  • 프로세스가 전환되면, 운영체제는 MMU에 등록된 페이지 테이블도 바꿔줌
  • 그래서 각 프로세스는 독립된 메모리 공간을 사용하는 것처럼 보임
  1. 페이지 폴트(Page Fault)
  • CPU가 가상 주소를 참조했는데, 그 주소가 아직 물리 메모리에 로드되지 않았다면
    → 페이지 폴트 발생
    → 운영체제가 디스크에서 해당 페이지를 로드함
    → 다시 CPU가 실행 이어감

HDD를 RAM처럼 빠르게

페이지 캐시(Page Cache)를 적극 활용하기

운영체제는 디스크에 접근할 때, 자주 읽는 파일을 RAM에 캐시해두는 전략을 사용함.

✅ 어떻게 동작하냐면?

  • HDD에서 파일을 처음 읽음
  • OS가 그 데이터를 RAM에 보관해 둠 (페이지 캐시)
  • 다음에 같은 파일을 읽을 때는 디스크가 아닌 RAM에서 바로 읽음 → 훨씬 빠름

📌 활용 방법

  • 자주 사용하는 파일을 cat, dd, head 등으로 한 번 읽어서 RAM에 올려두기
  • 커널이 자동으로 페이지 캐시를 활용함 (리눅스에서는 /proc/meminfo에서 확인 가능)

SSD + ZRAM/ZSwap + 캐싱 계층 구조

  • ZRAM 또는 ZSWAP 은 압축된 스왑 공간을 RAM 또는 디스크에 만드는 기술
  • HDD를 직접 빠르게 만들 수는 없지만, 메모리가 부족할 때 스왑 속도를 빠르게 만들어 전체 성능을 향상시킬 수 있음.

📌 이런 기술들을 쓰면, HDD로 스왑할 때보다 훨씬 빠르게 동작하게 됨

메모리 매핑 파일(Memory-Mapped Files, mmap)

운영체제는 HDD에 있는 파일을 가상 메모리에 직접 매핑해서 사용할 수 있음.

✅ mmap() 시스템 콜을 사용하면,

  • 파일의 내용을 메모리처럼 다룰 수 있음 (바이트 단위 접근 가능)
  • OS가 내부적으로 페이지 캐시 + TLB + 선제적 읽기 등을 활용하여 속도 향상

스왑 메모리

스왑 메모리의 기본 개념

  • RAM이 부족할 때, OS는 잠시 사용하지 않는 페이지(Page)디스크(보통 swap 공간)로 옮기고, RAM에 새로운 데이터를 로드할 수 있는 공간을 확보해.
  • 디스크에 저장된 페이지는 나중에 다시 필요해지면 다시 RAM으로 불러오고, 그 과정에서 또 다른 페이지가 스왑으로 밀려날 수도 있어.

동작 흐름

1. 프로세스 실행 → 메모리 부족 감지

  • 사용자가 프로그램을 실행하면 프로세스가 메모리에 올라감.
  • 여러 프로그램이 동시에 실행되면 RAM이 부족해질 수 있음.
  • 운영체제는 메모리 압력(Memory Pressure) 상태를 감지함.

2. 페이지 교체 필요 → 교체 대상 선정

  • OS는 RAM에서 오래 사용하지 않은 페이지를 찾아냄.
    이때 쓰이는 알고리즘이 대표적으로 아래와 같음:
    • LRU (Least Recently Used)
    • Clock (2nd chance)
    • FIFO (First-In, First-Out)

3. 선택된 페이지를 스왑 영역으로 이동

  • 교체 대상 페이지가 정해지면, 해당 내용을 Swap 영역(디스크)에 저장함.
  • 이 과정을 페이지 아웃(Page-Out)이라고 함.
  • 만약 그 페이지가 수정된 적이 있다면(Dirty Page), 반드시 디스크에 저장해야 함.

4. 새 페이지를 RAM에 로드

  • 그 자리에 다른 페이지를 RAM으로 가져옴.
    예: 새로 실행된 프로세스가 필요로 하는 코드나 데이터.
  • 이 과정을 페이지 인(Page-In)이라고 부름.

5. 스왑된 페이지가 다시 필요할 경우

  • 나중에 CPU가 다시 그 스왑된 페이지를 필요로 하면, Page Fault 발생.
  • 다시 그 페이지를 RAM으로 가져오고, 다른 페이지를 또 스왑으로 보냄.

TLB란?

TLB는 가상 주소 → 물리 주소로의 변환을 빠르게 하기 위한 캐시야.
운영체제의 가상 메모리 시스템에서, 페이지 테이블을 매번 접근하면 느리기 때문에, 최근 변환된 주소 정보를 따로 저장해두는 고속 메모리야.

왜 필요한가?

  • CPU는 가상 주소로 작업하고,
  • 실제 메모리는 물리 주소로 동작함.
  • 이걸 매번 페이지 테이블에서 찾아오면 속도 병목이 생겨.
  • 그래서 최근에 변환한 주소를 캐싱해두고, 다음에 또 같은 주소를 쓰면 빠르게 처리하려는 거지.

작동 흐름

  1. CPU가 가상 주소 접근 시도
  2. TLB에 해당 가상 주소가 있는지 확인
    • 있으면 → TLB Hit → 빠르게 물리 주소 반환
    • 없으면 → TLB Miss → 페이지 테이블 접근 → 변환 → TLB에 저장

주요 특징

항목설명
위치CPU 내부에 있음 (MMU와 가까움)
속도매우 빠름 (레지스터 수준)
크기작음 (수십~수백 개 엔트리)
방식보통 LRU 기반으로 교체

TLB는 페이지 테이블 접근을 줄여서 가상 메모리 시스템을 빠르게 만들어주는 핵심 캐시 장치.

프로세스와 페이지 테이블

1. 프로세스는 "자기만의 가상 주소 공간"을 가짐

  • 운영체제는 각 프로세스마다 독립된 가상 주소 공간을 제공해.
  • 그래서 프로세스 A와 B는 똑같은 0x4000 주소를 쓰더라도 서로 다른 공간을 참조하게 됨.
  • 이걸 가능하게 해주는 게 바로 페이지 테이블이야.

2. 프로세스마다 고유한 페이지 테이블을 갖는다

  • 페이지 테이블은 가상 주소 → 물리 주소 매핑 정보를 담고 있음.
  • 즉, 하나의 프로세스가 접근하는 가상 주소는, 그 프로세스만의 페이지 테이블을 통해 해당 프로세스 전용 물리 주소로 변환됨.

3. 문맥 교환(Context Switch) 시 페이지 테이블도 바뀐다

  • CPU가 A 프로세스 → B 프로세스로 전환할 때, 페이지 테이블의 기준 주소(보통 CR3 레지스터에 저장됨)도 함께 변경됨.
  • 그래야 CPU가 올바른 프로세스의 메모리를 참조할 수 있어.

예시
1. 프로세스 A가 0x1000 주소 접근 시도
2. OS는 A의 페이지 테이블을 참조해 0x1000 → 물리 주소 0xAB000으로 변환
3. 나중에 프로세스 B가 0x1000 접근하더라도,
B의 페이지 테이블을 통해 전혀 다른 물리 주소로 매핑됨 (예: 0xCD000)

페이지란?

페이지란 가상 메모리를 일정 크기로 나눈 블록 단위야.
보통 4KB, 8KB 같은 크기이고, 가상 주소와 물리 주소를 페이지 단위로 매핑하게 돼.

페이지가 필요한 이유

운영체제는 프로그램마다 독립적인 가상 주소 공간을 제공하고, 이 가상 주소를 실제 물리 메모리로 변환해야 하는데, 이걸 "페이지 단위로 변환"하면 훨씬 효율적이기 때문이야.

페이지 기반 메모리 관리 구조

  1. 가상 주소 공간: 프로세스가 바라보는 메모리 공간 (예: 0x0000 ~ 0xFFFF)
  2. 페이지 테이블: 각 가상 페이지가 어느 물리 페이지에 매핑되는지 기록
  3. 물리 주소 공간: 실제 RAM 주소

페이지 주소 변환 과정 (페이징 구조)

예: 가상 주소 0x5F30, 페이지 크기 4KB = 4096 bytes = 2^12
→ 상위 비트(페이지 번호) + 하위 비트(페이지 내 오프셋)

가상 주소  = [페이지 번호 | 오프셋]
          = [   20bit    |  12bit ]  (32bit 시스템 기준)

1. 페이지 번호로 → 페이지 테이블 참조
2. 물리 프레임 번호 얻음
3. 물리 주소 = [물리 프레임 번호 | 오프셋]

페이지 vs 프레임

용어설명
페이지(Page)가상 메모리에서 나눈 고정 크기 블록
프레임(Frame)물리 메모리에서 나눈 고정 크기 블록
매핑페이지 테이블을 통해 각 페이지가 어떤 프레임에 있는지 연결

궁금했던 내용 알아보기

페이지 테이블이 너무 많으면 어떻게 되지?

1. 메모리 사용량 증가

  • 가상 주소 공간이 크면, 페이지 수도 많아짐.
    예:
    • 32비트 주소 공간 + 4KB 페이지 → 약 100만 개 페이지 → 100만 개 항목
    • 64비트 주소 공간 + 4KB 페이지 → 2^52개 페이지 → 현실적으로 불가능
  • 각 프로세스마다 고유한 페이지 테이블을 갖기 때문에, 페이지 테이블이 커지면
    → 프로세스 하나만으로도 수 MB ~ 수 GB의 메모리 낭비가 발생 가능

2. 접근 속도 느려짐

  • 변환할 주소가 너무 많아지면, 하나의 물리 주소를 찾기 위해 테이블을 너무 많이 탐색해야 해.
  • 캐시(TLB)에 다 들어가지도 못함 → TLB Miss 증가 → 성능 저하

3. 시스템 스케일에 제약

  • 다수의 프로세스가 동시에 실행되면,
    각자의 페이지 테이블로 인해 운영체제의 메모리 공간도 부담 증가
  • 커널이 페이지 테이블만 관리하느라 메모리를 허비하게 됨

해결 방법

1. 다단계 페이지 테이블 (Multi-Level Page Table)

모든 페이지 테이블을 한꺼번에 갖고 있지 않고, 필요할 때만 부분적으로 메모리에 올리는 구조

  • 예: 2단계 페이지 테이블
    • 상위 테이블: Page Directory
    • 하위 테이블: Page Table
  • 사용 중인 주소 공간만 매핑 → 메모리 효율 향상
  • 흔한 구조:
    • 32bit 시스템: 2단계
    • 64bit 시스템: 3~4단계 구조 사용

2. 인버티드 페이지 테이블 (Inverted Page Table)

모든 프로세스가 하나의 페이지 테이블을 공유하고,
물리 메모리 기준으로 가상 주소를 거꾸로 찾는 구조

  • 메모리 절약에 유리
  • 해시 기반 탐색 사용
  • 구조는 복잡해지고, TLB 의존도는 높아짐

페이지 테이블 구조는 어떻게 되어 있을까?

하나의 엔트리는 보통 4~8바이트 정도고, 다음과 같은 정보들을 담고 있어:

비트의미
P (Present)이 페이지가 현재 메모리에 있는지 여부
R/W (Read/Write)읽기/쓰기 권한
U/S (User/Supervisor)사용자/커널 접근 권한
A (Accessed)접근된 적 있는지 여부
D (Dirty)수정된 적 있는지 여부
PFN (Page Frame Number)실제 물리 메모리 프레임 번호
기타캐시 비활성화, 글로벌 페이지 여부 등등

운영체제는 메모리 부족을 어떻게 감지할까?

1. 물리 메모리 사용량 추적 (Global Level)

운영체제는 다음과 같은 메모리 사용량 지표들을 계속 추적하고 있어:

항목설명
Free memory아무도 사용하지 않고 있는 여유 메모리
Cached memory파일 캐시 등으로 사용 중이지만 필요시 해제 가능한 메모리
Active/Inactive pages최근에 접근된 페이지와 한동안 접근되지 않은 페이지
Swap usage얼마나 많은 페이지가 디스크로 스왑됐는지

이 수치들이 임계값(threshold) 이하로 떨어지면, 운영체제는 메모리 부족이라고 판단함.

profile
취업 준비생 낚곰입니다!! 반갑습니다!!

0개의 댓글