728x90

MMU 한눈에: 개요와 핵심 개념 (시리즈 1/3)

요약

  • MMU(Memory Management Unit)는 가상 주소(VA)를 물리 주소(PA)로 변환하고, 접근 권한과 메모리 속성을 검사해 프로세스 격리와 메모리 보호를 제공합니다.
  • 이 글은 MMU의 역할, 기본 용어, 동작 흐름을 쉬운 예시와 그림으로 설명합니다.

(그림) MMU 전체 구조

목차

  1. 왜 MMU가 필요한가?

  2. 기본 용어 정리

  3. MMU의 동작 흐름(쉽게)

  4. 실무에서 자주 보는 개념: TLB, 페이지, 페이지 테이블

  5. 다음 글 예고: 내부 구조와 ARM 특성

  6. 왜 MMU가 필요한가?

  • 프로세스 격리: 각 프로세스가 서로의 메모리를 덮어쓰지 못하도록 함.
  • 보호: 커널 메모리는 유저 모드에서 읽기/쓰기/실행 못 하게 설정.
  • 가상 메모리: 물리 메모리보다 큰 주소 공간 제공(스왑 등).
  • 메모리 속성 관리: 캐시/비캐시, Device 영역 제어.

간단한 비유

  • 도서관의 색인 카탈로그: 사용자가 찾는 책(가상 주소)을 실제 선반(물리 주소) 위치로 찾아주는 역할. 자주 찾는 책은 계산해 놓은 책꽂이(=TLB)에 저장.
  1. 기본 용어 정리 (요약)
  • 가상 주소(VA) / 물리 주소(PA)
  • 페이지(page): 일반적으로 4KB 등, 변환의 최소 단위
  • 페이지 테이블(Page Table) / PTE
  • TLB(Translation Lookaside Buffer): 변환 캐시
  • ASID: 주소 공간 식별자
  1. MMU의 동작 흐름(한 번에 보기)

1. CPU가 VA로 접근.

2. MMU가 TLB에서 매핑을 찾음.

  • 있으면 PA로 바로 접근.

  • 없으면 페이지 테이블을 조회해서 PTE를 얻음

3. PTE의 권한/속성 검사.

  • 실패하면 페이지 폴트(예외).

4. 변환 결과를 TLB에 저장하고 메모리에 접근.

핵심 개념 짚기

  • TLB miss가 비용으로 이어짐 → hugepage, ASID 전략 고려.
  • 페이지 크기 선택(4KB vs 2MB 등)은 TLB 부담과 단편화의 절충.
  • 페이지 테이블은 다단계(레벨) 구조가 일반적.
  1. 실무에서 자주 보는 개념: TLB, 페이지, 페이지 테이블

이 섹션에서는 개발·디버깅·성능 최적화 관점에서 흔히 마주치는 개념들을 실무 중심으로 정리합니다.

4.1 TLB (Translation Lookaside Buffer)

  • 역할: VA → PA 변환 결과(주로 상위 PFN과 몇몇 속성)를 캐시해서 주소 변환 비용을 크게 줄여 줍니다.
  • 왜 중요한가:
    • TLB miss가 발생하면 MMU는 다단계 페이지 테이블을 조회해야 하므로 지연이 큽니다(메모리 접근 수십~수백 배 비용).
    • 반복적인 메모리 접근 패턴에서 TLB hit 비율은 성능에 직접적인 영향을 줍니다.
  • 실무 포인트:
    • 큰 페이지(hugepages, 2MB/1GB 등)를 사용하면 TLB 엔트리 당 커버하는 메모리 범위가 늘어나 TLB miss가 줄어듭니다. 그러나 내부 단편화와 메모리 사용의 유연성 손실이 생깁니다.
    • 멀티스레드/멀티프로세스 환경: 컨텍스트 스위치 시 TLB를 플러시하면 성능이 떨어집니다. ASID가 있으면 각 주소 공간의 엔트리를 구분해 플러시를 줄일 수 있습니다.
    • 멀티코어 시스템: 페이지 테이블 변경 시 각 코어의 TLB를 동기화(“TLB shootdown”)해야 하므로 비용 발생. 이 부분이 NUMA/대규모 서버에서 성능 병목이 되기도 합니다.
  • 관찰 방법:
    • Linux: perf stat -e cpu/cache-misses, dTLB_load_misses 등을 이용해 TLB miss 관련 이벤트를 볼 수 있음. (하드웨어/커널 버전 따라 이벤트 이름 다름)
    • 커널 개발: /proc/kpageflags, /proc/pid/pagemap 등을 통해 페이징 동작을 분석.

4.2 페이지(Page)와 페이지 크기

  • 페이지란: 가상-물리 변환의 기본 단위(가장 흔한 크기: 4KB).
  • 페이지 크기가 중요한 이유:
    • 작은 페이지(4KB)는 메모리 할당의 세분화에 유리하지만, TLB 압박이 큼.
    • 큰 페이지(2MB/1GB 등)는 TLB 부담을 줄여 성능을 올리지만 내부 단편화(메모리 낭비) 위험이 있음.
  • 용도별 선택:
    • 데이터베이스, HPC, 가상화: 메모리 접근 패턴이 크고 연속적이면 hugepage 사용 권장.
    • 일반 애플리케이션: 기본 4KB로 충분한 경우가 많음.
  • 실무 팁:
    • Linux에서 transparent hugepage(THP) 기능으로 자동으로 2MB 페이지를 만들기도 함. 성능 프로파일링으로 장단점 판단 필요.
    • 페이지 정렬/할당 정책(예: vmalloc vs kmalloc, get_free_pages의 order)을 이해하면 커널 메모리 이슈 파악에 도움.

4.3 페이지 테이블(Page Table)

  • 다단계 구조:
    • 다단계(page table levels)는 큰 가상 주소 공간을 적은 메모리로 표현하기 위해 사용합니다(L0/L1/L2/...).
    • 각 레벨 엔트리는 다음 레벨 테이블의 물리 주소이거나 최종 물리 페이지를 가리킵니다(“block” 엔트리 가능).
  • PTE (Page Table Entry) 주요 필드(개념적):
    • Output Address (물리 페이지 프레임 상위 비트)
    • Valid bit / Table bit (다음 레벨 테이블을 가리키는지 여부)
    • AP (Access Permission) — 읽기/쓰기/특권 구분
    • AF (Access Flag) — 페이지가 접근되었는지 표시
    • Dirty bit — 쓰기 발생 여부
    • AttrIndex / MAIR 인덱스 — 캐시/Device 속성 결정
    • XN / UXN (실행금지 비트)
  • 실무에서 확인·디버깅하는 방법:
    • 사용자 관점:
      • cat /proc/self/maps 또는 /proc//maps: 가상 메모리 영역(프로세스의 메모리 맵) 확인.
      • /proc//pagemap: 가상 페이지와 물리 프레임 매핑(원시 데이터, 루트 권한 필요).
    • 커널/부트 관점:
      • 부트 초기에는 identity map(가상==물리)을 사용해 초기화가 단순해짐. 이후 정식 페이지 테이블로 전환.
      • 커널 로그(dmesg)에 초기 MMU/TTBR/TCR/MAIR 설정 값을 찍어 두면 부트 문제 추적에 유리.
    • 성능 고려사항:
    • 페이지 테이블의 메모리 접근(테이블 워크)은 캐시 친화적으로 설계되어야 함. 즉, 페이지 테이블 자체가 잘 캐시되도록 엔트리 배치·정렬을 고려.
    • PTE 크기(예: 8바이트)와 페이지 테이블 전체 크기에 따라 메모리 오버헤드가 달라짐. 64-bit 시스템에서는 페이지테이블 메모리 비용이 커질 수 있음.
  • 안전성/보안:
    • Execute Never (XN) 등의 비트를 활용해 데이터 영역의 코드 실행을 방지(W^X 정책).
    • 사용자-커널 분리를 통해 취약점으로 인한 권한 상승을 방지.
  1. 다음 글 예고
  • 다음 포스트(시리즈 2)에서는 페이지 테이블 구조와 PTE 필드, 권한 비트, 캐시 속성(MAIR) 등 내부를 자세히 다룹니다.

참고 및 읽을거리

  • ARM Architecture Reference Manual (MMU 섹션)

저자 노트: 이 글은 초심자도 개념을 빠르게 이해하도록 의도했습니다. 다음 글에서 페이지 테이블 레이아웃과 ARM 특화 레지스터(TTBR, TCR, MAIR, SCTLR 등)를 시각적으로 풀어드릴게요.

복사했습니다!