CSAPP/9장

[CSAPP] 9장 가상 메모리(Virtual Memory) - 9.5 ~ 9.8

넌뭐가그렇게중요해 2025. 4. 22. 19:35

9.5 가상 메모리를 통한 메모리 보호

가상 메모리 시스템은 프로세스마다 독립된 주소 공간을 제공할 뿐 아니라, 페이지 단위로 접근 권한을 통제할 수 있는 메커니즘을 갖추고 있습니다.

페이지 테이블 엔트리(PTE)의 권한 비트

  • 각 PTE에 SUP(kernel vs user), READ, WRITE 비트를 두어 접근을 제어합니다.
    • 사용자 모드가 SUP=1인 페이지 접근 시 Segmentation Fault 발생 
    • 읽기/쓰기 비트가 맞지 않으면 Protection Fault 발생

메모리 보호 다이어그램

┌─────────────┐   PTE: SUP=0, R=1, W=0
│ Virtual VP0 │ ──▶│ Physical PP2 │  (읽기만 가능)
└─────────────┘      Permissions: r/o  

┌─────────────┐   PTE: SUP=0, R=1, W=1
│ Virtual VP1 │ ──▶│ Physical PP4 │  (읽기·쓰기 가능)
└─────────────┘      Permissions: r/w  

┌─────────────┐   PTE: SUP=1, R=1, W=1
│ Virtual VP2 │ ──▶│ Physical PP7 │  (커널 전용)
└─────────────┘      Permissions: superuser only

해설: 사용자 모드에서 VP2에 접근하면 SUP 위반으로 예외가 발생합니다.


9.6 주소 변환 메커니즘

CPU가 가상 주소를 물리 주소로 변환하는 과정과 이를 최적화하는 TLB 기법을 살펴봅니다.

9.6.1 VPN/VPO 분할과 다단계 페이지 테이블

 

  • 가상 주소 = VPN ∥ VPO (예: 64비트 주소에서 상위 52비트가 VPN, 하위 12비트가 VPO)
  • 다단계 페이지 테이블: 4단계(예: x86-64)로 나누어, 실제 사용되는 페이지 테이블 엔트리만 메모리에 유지

9.6.2 TLB(Translation Lookaside Buffer)

  • TLB: 최근 사용된 VPN→PPN 매핑을 캐시하는 소규모 고속 메모리
  • 변환 시:
    1. TLB 히트 → 즉시 PPN 얻어 물리 주소 생성
    2. TLB 미스 → 다단계 테이블 워크 후 TLB에 저장

9.6.3 캐시와의 중첩 최적화

  • VPO 비트와 캐시 인덱스 비트가 동일하게 배치되어, TLB 조회와 L1 캐시 접근을 병렬화 가능

 

9.7 사례 연구: Intel Core i7 / Linux 메모리 시스템

9.7.1 Intel Core i7 주소 변환·캐시 계층

  • L1 TLB: 명령어 128 entry, 데이터 64 entry
  • L2 TLB: 1536 entry로 L1 미스를 처리
  • 캐시: L1(32KB·8-way), L2(256KB), L3(8MB)

9.7.2 Linux 가상 메모리 자료구조

task_struct ──▶ mm_struct ──▶ vm_area_struct ──▶ … 
   │             │               │
   │             │               ├─ vm_start, vm_end (영역 경계)
   │             │               ├─ vm_flags (공유·사적)
   │             │               └─ vm_page_prot (접근 권한)
   │             └─ pgd → CR3 레지스터에 로드
   └─ PID, 스케줄링 정보 등

해설: task_struct → mm_struct → 연결 리스트 형태의 vm_area_struct로 프로세스별 영역을 관리합니다.

9.7.3 페이지 폴트 처리

 

  • 주소 유효성 검사: 해당 가상 주소가 어떤 vm_area_struct 안에 있는지 확인
  • 권한 검사: PTE의 권한 비트(SUP, READ, WRITE) 검증
  • 수요 페이징: 디스크에서 페이지 로드 후 물리 메모리에 매핑

9.8 메모리 매핑(Memory Mapping)

9.8.1 공유 객체(Shared Objects)와 Copy-on-Write

  • 공유 매핑: .so 파일을 다수 프로세스가 동일 물리 페이지로 매핑
  • 사적 매핑(Copy-on-Write): 처음에는 읽기 전용으로 공유하다, 쓰기 시점에만 페이지를 복제
프로세스 A, B
┌─────────────┐       ┌─────────────┐
│ area_A: COW │◀─────▶│ area_B: COW │  (같은 PP)
└─────────────┘       └─────────────┘
  → A가 쓰기 시 ─────▶ 페이지 복제 후 PP₂ 사용 :contentReference[oaicite:12]{index=12}

9.8.2 fork() 재고찰

  • fork() 시 mm/mm_area/page table을 그대로 복제하고 모든 페이지를 읽기 전용·COW로 표시
  • 이후 쓰기 시점에만 실제 복사되어 독립된 사본을 갖게 됩니다.

9.8.3 execve() 재고찰

[기존 프로세스 VAS 영역 삭제] 
     ↓
[.text/.data: 파일 기반 매핑]
[.bss/heap/stack: 익명(demand-zero) 매핑]
[공유 라이브러리: ld-linux.so에 의해 동적 링크 후 매핑]
     ↓
[PC를 진입점(entry)으로 설정 후 실행]

 

해설: 실행 파일을 메모리에 로드할 때, 실제 복사는 없고 모두 메모리 매핑으로 처리됩니다

9.8.4 사용자 수준 매핑: mmap

  • mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)
    → 익명 사적 매핑으로 크기가 length인 zero-initialized 영역 생성
  • 파일 매핑 시 fd, offset 지정 가능

 

참고 인용 출처

 

  • Virtual Memory Protection (Wikipedia) 
  • Copy-on-Write (Wikipedia) 
  • TLB (Wikipedia) 
  • Memory Mapping (GeeksforGeeks) 
  • fork() COW 동작 (Reddit OSDev)
  • Program Loading & execve (Bodun Hu) 
  • vm_area_struct 구조 (Huihoo)
  • Linux page fault handling (GeeksforGeeks) 
  • Intel Core i7 TLB/Cache 아키텍처 (WPI)