PROJECT-3 (VM)

박지성 ·2025년 5월 29일
post-thumbnail

목차

  1. 폴더 구조
  2. 개발 순서
  3. 테스트 케이스
  4. 코드 흐름

폴더 구조

vm/

  • vm.c: 가상 메모리 전반을 관리하는 인터페이스
  • frame.c: 프레임 할당 및 교체 로직
  • anon.c: Anonymous page (파일 없이 메모리에만 존재하는 페이지) 처리
  • file.c: File-backed page 처리 (mmap 등)
  • page.c: Supplemental Page Table(SPT) 핵심 로직 (페이지 등록/탐색 등)
  • uninit.c: Lazy loading을 위한 초기화 구조

userprog/

  • exception.cdo_page_fault()에서 Page Fault 핸들링
  • process.c: 프로세스 생성 시 SPT 초기화

threads/

  • palloc.c: 페이지 단위 물리 메모리 할당
  • synch.c: 동기화 (락 등)
  • thread.c: 현재 스레드 정보 접근

개발 순서 (추천)

1. Introduction

프로젝트 목표: 가상 메모리(Virtual Memory)를 구현하여 사용자 프로그램의 주소 공간을 효율적으로 관리

학습 내용 : SPT, 프레임 관리, 페이지 폴트 처리, 스택 확장, mmap, 스왑 등) 숙지

핵심 기능

  • Lazy Loading
  • Anonymous / File-backed Page
  • Stack Growth
  • Memory Mapping (mmap)
  • Swap In/Out
  • (옵션) Copy-on-write

테스트 기준tests/vm/*tests/userprog/* 일부 테스트 통과가 목표


2. Memory Management (전반적인 흐름 이해)

책임 구조

  • 사용자 주소 공간은 Supplemental Page Table (SPT)로 관리한다
  • SPT는 사용자 가상 주소와 해당 페이지 정보를 매핑하는 해시 테이블

핵심 파일

  • vm/page.c: 페이지 등록/탐색 (spt_find_page()spt_insert_page())
  • vm/vm.cvm_alloc_page()vm_claim_page() 등 인터페이스
  • userprog/exception.cdo_page_fault()에서 페이지 폴트 처리

3. Anonymous Page (anon.c)

역할: 파일 없이 메모리로만 구성된 페이지 (ex. Stack, Heap)

구현 순서

  1. anon_page_init() 구현
  2. anon_initializer() 구현 및 uninit_new()에서 등록
  3. anon_swap_in()anon_swap_out()은 초기에는 간단히 구현

테스트 연관

  • vm/lazy-anon
  • vm/swap-anon (스왑 구현 후)

4. Supplemental Page Table (page.c)

역할: 가상 주소 ↔ 페이지 정보 매핑

구현 순서

  1. page_hash() / page_less() / page_destroy() 함수 등록
  2. spt_find_page(): 주소에 해당하는 페이지 탐색
  3. spt_insert_page(): 주소에 새 페이지 등록
  4. spt_remove_page()supplemental_page_table_copy() 등

구조체

  • struct page
  • struct supplemental_page_table

테스트 연관

  • 모든 페이지 관련 테스트의 기반

5. Lazy Loading (uninit.cdo_page_fault())

역할: 페이지를 처음 접근할 때 실제 메모리를 할당하고, 초기화함

구현 순서

  1. struct uninit_page 구조 이해
  2. do_page_fault()에서 SPT에서 찾고, 없다면 vm_stack_growth() 또는 실패 처리
  3. vm_claim_page()에서 initializer() 호출 -> anon_initializer() 등

관련 함수

  • do_page_fault()vm_do_claim_page()uninit_initialize()

테스트 연관

  • vm/lazy-*
  • vm/pt-* 일부

6. Stack Growth

역할: 사용자가 스택을 점점 아래로 확장할 때 동적으로 페이지를 추가

구현 순서

  1. vm_stack_growth() 구현
  2. do_page_fault()에서 fault 주소가 스택으로 확장 가능한 범위인지 확인 (is_stack_growth())

고려사항

  • PHYS_BASE 기준으로 아래쪽으로 성장
  • 최대 스택 크기 제한 (~8MB)

테스트 연관

  • vm/pt-grow-stack
  • vm/pt-big-stk-obj

7. File-backed Page (file.c)

역할: 파일 내용을 페이지로 매핑 (mmap 등)

구현 순서

  1. file_backed_initializer()file_backed_swap_in/out() 등 구현
  2. mmap syscall과 연결하여 vm_alloc_page_with_initializer() 활용
  3. do_mmap()do_munmap() 구현

테스트 연관

  • vm/mmap-*
  • vm/page-merge-*vm/page-shuffle

8. Swap In/Out

역할: 메모리가 부족할 때 디스크로 페이지를 임시 저장하는 기능

구현 순서

  1. swap.c에 bitmap 기반 슬롯 관리
  2. frame.c: 프레임 부족 시 교체 (Clock 등)
  3. anon_swap_in()anon_swap_out() 완성

테스트 연관

  • vm/swap-*
  • vm/lazy-anon 등

9. Copy-on-write (추가 구현)

역할fork() 시 페이지 복사 대신 공유하고, 쓰기 시 복사

구현 포인트

  • page->writable을 false로 설정
  • page fault 시 복사 수행
  • refcount 기반 관리

테스트 연관

  • vm/cow/cow-simple

요약 개발 순서

단계구현 파일주요 테스트
Anonymousanon.clazy-anonswap-anon
SPT 연결page.c모든 테스트 기반
Lazy Loadinguninit.cdo_page_faultlazy-*pt-*
Stack Growthvm.cexception.cpt-grow-*pt-big-stk-obj
File-backedfile.cmmap-*page-merge-*
Swapswap.cframe.cswap-*
COWpage.cexception.ccow-simple

테스트 케이스

1. 페이지 폴트 처리 및 스택 확장 (Page Fault & Stack Growth)

주요 파일: userprog/exception.c의 page_fault() 함수, vm/vm.c (또는 유사 파일) 내의 페이지 로딩 및 스택 확장 로직.

테스트 그룹: tests/vm/pt-*.c (Page Table tests)

  • 핵심 기능:
    • 사용자 프로그램이 아직 물리 메모리에 없는 (또는 접근 권한이 없는) 가상 주소에 접근했을 때 페이지 폴트(page fault)가 발생하는 것을 감지하고 이를 처리합니다.
    • *보조 페이지 테이블(Supplemental Page Table, SPT)**을 조회하여 해당 가상 페이지의 상태(디스크에 있는지, 스왑 영역에 있는지, 아니면 새로 만들어야 하는지 등)를 파악합니다.
    • 필요한 데이터를 물리 메모리 프레임(physical memory frame)으로 가져오고(페이지 로딩), CPU의 페이지 테이블(MMU가 사용하는 페이지 테이블, 예: x86-64의 PML4)을 업데이트하여 가상 주소와 물리 주소를 매핑합니다.
    • 특히, 스택 포인터(%rsp) 근처의 유효한 영역에서 페이지 폴트가 발생하면, 스택을 자동으로 한 페이지씩 확장해줍니다.
    • 잘못된 메모리 접근(예: 할당되지 않은 영역, 커널 영역, 읽기 전용 영역에 쓰기 시도) 시에는 프로세스를 정상적으로 종료시킵니다.
  • 주요 테스트 케이스 및 검증 내용:
    • pt-grow-stack: 정상적인 스택 확장 (한 페이지).
    • pt-grow-bad: 부적절한 주소에서의 스택 확장 시도 시 프로세스 종료.
    • pt-big-stk-obj: 큰 객체 할당을 위한 다중 페이지 스택 확장.
    • pt-bad-addrpt-bad-read: 유효하지 않은 주소 접근 시 프로세스 종료.
    • pt-write-codept-write-code2: 읽기 전용인 코드 영역에 쓰기 시도 시 프로세스 종료.
    • pt-grow-stk-sc: 시스템 콜 중 발생하는 스택 확장의 정상 처리.

2. 페이지의 종류 및 지연 로딩 (Page Types & Lazy Loading)

주요 파일: vm/vm.cvm/anon.cvm/file.cvm/uninit.c (KAIST Pintos 기준). struct page의 다양한 타입(VM_ANONVM_FILEVM_UNINIT) 및 관련 핸들러 함수들.

테스트 그룹: tests/vm/page-*.ctests/vm/lazy-*.c

  • 핵심 기능:
    • 익명 페이지(Anonymous Page, VM_ANON): 스택, 힙, 또는 BSS 세그먼트처럼 특정 파일과 연결되지 않은 페이지들을 관리합니다. 처음 접근 시 0으로 초기화된 물리 프레임에 연결됩니다 (지연 로딩).
    • 파일 기반 페이지(File-backed Page, VM_FILE): 실행 파일의 코드/데이터 세그먼트나 메모리 매핑된 파일의 내용을 담는 페이지입니다. 처음 접근 시 파일로부터 해당 내용을 읽어와 물리 프레임에 로드합니다 (지연 로딩).
    • 미초기화 페이지(Uninitialized Page, VM_UNINIT): 페이지가 처음 요청되었지만 아직 내용이 로드되지 않았거나 타입이 결정되지 않은 상태를 나타냅니다. 페이지 폴트 시 실제 타입(ANON 또는 FILE)으로 전환되며 초기화됩니다.
    • 이러한 페이지들을 보조 페이지 테이블(SPT)을 통해 효율적으로 관리합니다.
  • 주요 테스트 케이스 및 검증 내용:
    • page-linearpage-parallelpage-shuffle: 익명 페이지의 기본적인 할당, 접근, 해제 및 여러 프로세스/스레드에서의 동시 사용 시나리오를 검증합니다.
    • page-merge-*: (Pintos 기본 요구사항은 아닐 수 있으나) 인접한 페이지들의 관리 효율성을 간접적으로 테스트할 수 있습니다.
    • lazy-anon: 익명 페이지가 실제로 접근될 때까지 물리 메모리 할당 및 초기화가 지연되는지 확인합니다.
    • lazy-file: 파일 기반 페이지가 실제로 접근될 때까지 파일로부터 데이터 로딩이 지연되는지 확인합니다.

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

주요 파일: userprog/syscall.c (mmap, munmap 시스템 콜 처리), vm/file.c (파일 기반 페이지 처리 로직 연관).

테스트 그룹: tests/vm/mmap-*.c

  • 핵심 기능:
    • mmap 시스템 콜: 지정된 파일을 사용자 프로세스의 가상 주소 공간의 특정 영역에 매핑합니다.
      • 요청된 가상 주소 영역에 대해 SPT에 파일 기반 페이지(VM_FILE)들을 설정합니다. 이때도 지연 로딩을 사용하여, 실제 메모리 접근이 발생할 때까지 파일 내용을 물리 메모리로 읽어오지 않습니다.
      • 파일 내용에 대한 읽기/쓰기 접근을 일반 메모리 접근처럼 처리할 수 있게 합니다.
      • 다양한 오류 조건(잘못된 파일 디스크립터, 주소 정렬 오류, 영역 겹침, 파일 크기 초과 등)을 처리해야 합니다.
    • munmap 시스템 콜: 기존의 메모리 매핑을 해제합니다.
      • 매핑된 페이지들 중 내용이 변경된(dirty) 페이지가 있다면, 변경 사항을 실제 파일에 다시 기록(write-back)합니다.
      • 관련된 SPT 항목들을 제거하고, 사용 중이던 물리 프레임을 반환합니다.
    • 프로세스 종료 시 모든 mmap된 영역은 자동으로 munmap 처리되어야 합니다.
  • 주요 테스트 케이스 및 검증 내용:
    • mmap-readmmap-write: 매핑된 메모리를 통한 파일 읽기 및 쓰기, 쓰기 후 파일 반영(write-back) 확인.
    • mmap-close: 매핑 후 원본 파일 디스크립터를 닫아도 매핑이 유지되는지 확인.
    • mmap-unmap: 정상적인 매핑 해제 및 해제 후 접근 시도 시 오류 처리.
    • mmap-exit: 프로세스 종료 시 자동 unmap 및 dirty 페이지의 write-back.
    • mmap-ro: 읽기 전용 매핑 후 쓰기 시도 시 오류 처리.
    • 각종 오류 상황 테스트: mmap-overlapmmap-twicemmap-bad-fdmmap-misalignmmap-nullmmap-over-code/data/stkmmap-zerommap-zero-lenmmap-offmmap-kernel 등등.

4. 스와핑 및 페이지 교체 (Swapping & Page Replacement)

주요 파일: vm/vm.c (또는 프레임 관리 및 페이지 교체 로직이 있는 파일), vm/anon.c (익명 페이지 스왑 처리), devices/disk.c (스왑 디스크 사용).

테스트 그룹: tests/vm/swap-*.c

  • 핵심 기능:
    • 물리 메모리 프레임이 부족할 때, 현재 사용되지 않는 페이지를 디스크의 스왑 공간(swap space)으로 내보내는(swap-out) 기능을 구현합니다.
    • 어떤 페이지를 스왑 아웃할지 결정하는 페이지 교체 알고리즘(page replacement algorithm) (예: Clock, LRU 등)을 구현합니다.
    • 스왑 아웃된 페이지에 다시 접근하려고 하면, 페이지 폴트가 발생하고, 해당 페이지의 내용을 스왑 공간에서 다시 물리 메모리로 가져옵니다(swap-in).
    • *프레임 테이블(Frame Table)**을 사용하여 물리 프레임의 상태(사용 중/비어있음, 어떤 페이지와 연결되어 있는지, 교체 알고리즘을 위한 정보 등)를 관리합니다.
    • 파일 기반 페이지의 경우, 스왑 아웃 시 스왑 공간 대신 원본 파일에 변경 내용을 기록할 수도 있습니다. (KAIST Pintos 명세 확인 필요)
  • 주요 테스트 케이스 및 검증 내용:
    • swap-anon: 익명 페이지의 정상적인 스왑 아웃 및 스왑 인 동작 확인.
    • swap-file: 파일 기반 페이지의 스왑 아웃 및 스왑 인 동작 확인.
    • swap-iter: 반복적인 스왑 발생 시 데이터 무결성 및 시스템 안정성 확인.
    • swap-forkfork와 스와핑이 동시에 발생하는 복잡한 상황에서의 안정성 테스트.

5. Copy-on-Write (COW) (선택 사항/추가 기능)

주요 파일: userprog/process.c (fork 구현 시), vm/vm.c (또는 페이지 관리 로직).

테스트 그룹: tests/vm/cow-simple.c (KAIST Pintos의 경우 tests/vm/cow/ 하위에 있을 수 있음)

  • 핵심 기능:
    • fork 시스템 콜을 통해 자식 프로세스를 생성할 때, 부모의 메모리 공간을 즉시 물리적으로 복사하는 대신, 부모와 자식이 동일한 물리 프레임을 공유하도록 합니다. 이때 해당 페이지들은 읽기 전용(read-only)으로 표시됩니다.
    • 부모 또는 자식 프로세스가 공유된 페이지에 쓰기를 시도하면 페이지 폴트가 발생합니다.
    • 이 페이지 폴트 핸들러는 해당 페이지에 대해서만 새로운 물리 프레임을 할당하고 내용을 복사한 뒤, 쓰기 작업을 허용합니다. 다른 프로세스는 여전히 이전 프레임을 (읽기 전용 또는 자신만의 복사본으로) 사용합니다.
    • 이를 통해 fork의 성능을 향상시키고 메모리 사용량을 줄일 수 있습니다.
  • 주요 테스트 케이스 및 검증 내용:
    • cow-simplefork 후 부모/자식 중 한쪽에서 공유 페이지에 쓰기를 시도할 때 COW가 정상적으로 동작하여 해당 페이지만 복사되고, 다른 쪽의 페이지는 영향을 받지 않는지 확인합니다.

코드 흐름

직접 흐름을 파악하는 것을 추천합니다. 참고용 입니다.

초기화 (System Boot & Process Creation)

  • main() (threads/init.c)
    • palloc_init(): 물리 메모리 페이지 할당자 초기화 (이미 프로젝트 1, 2에서 사용).
    • vm_init() (또는 vm_anon_initvm_file_init 등): 가상 메모리 서브시스템의 전역적인 자료구조 초기화.
      • 프레임 테이블(Frame Table) 초기화: 물리 프레임들을 관리할 자료구조 (예: 배열, 리스트)를 준비하고, 락(lock)을 초기화합니다. (vm/vm.c 또는 유사 파일)
      • 스왑 공간(Swap Space) 초기화: 스왑 디스크를 찾고, 스왑 슬롯 관리를 위한 비트맵 등을 초기화합니다. (vm/vm.c 또는 vm/anon.cdevices/disk.c 연관)
  • process_create_initd() / process_exec() (userprog/process.c)
    • 새로운 프로세스(스레드)가 생성될 때:
      • thread_create() (threads/thread.c)
        • init_thread() 내부 또는 직후:
          • 보조 페이지 테이블(Supplemental Page Table, SPT) 초기화: 각 스레드(프로세스)별 SPT (예: 해시 테이블)를 생성하고 초기화합니다. struct thread에 SPT 포인터 필드를 추가하고, 이 함수 내에서 supplemental_page_table_init(&curr->spt) (가칭) 같은 함수를 호출합니다. (vm/vm.c 또는 유사 파일)
  • load() (userprog/process.c): 실행 파일을 메모리에 적재할 때
    • ELF 파일 헤더를 읽고, 코드(code) 세그먼트와 데이터(data) 세그먼트 정보를 파악합니다.
    • 각 세그먼트에 대해 load_segment() 함수가 호출됩니다.
    • load_segment() 내부 (수정 필요):
      • 기존에는 palloc_get_page()로 물리 프레임을 직접 할당하고 install_page()로 매핑했습니다.
      • 프로젝트 3에서는:
        1. 세그먼트의 각 가상 페이지에 대해 보조 페이지 테이블(SPT)에 엔트리(entry)를 생성합니다.
          • 이때 페이지 타입은 VM_FILE (실행 파일의 내용을 담으므로) 또는 VM_UNINIT (지연 로딩을 위해)으로 설정하고, 파일 정보(실행 파일, 오프셋, 읽을 크기 등)를 함께 저장합니다.
          • 예: vm_alloc_page_with_initializer(VM_FILE, upage, writable, lazy_load_segment, file_info) (가칭, vm/vm.c)
        2. 물리 메모리 할당 및 파일 읽기는 페이지 폴트 발생 시로 미룹니다 (Lazy Loading). CPU의 페이지 테이블(PML4)에는 아직 매핑하지 않습니다.

2. 페이지 폴트 처리 (Page Fault Handling)

  • CPU가 페이지 폴트 예외 발생시킴 (잘못된 메모리 접근, 존재하지 않는 페이지 접근, 권한 없는 접근 등)
  • pg_fault_handler() (IDT에 등록된 핸들러, threads/intr-stubs.S에서 호출)
    • page_fault() (userprog/exception.c) - 여기가 핵심 수정 지점입니다!
      1. 폴트 정보 분석struct intr_frame *f에서 폴트가 발생한 가상 주소(fault_addr), 오류 코드(error_code), 스택 포인터(f->rsp 또는 64비트에서는 f->R.rsp), 유저/커널 모드 등을 가져옵니다.
      2. 폴트 유효성 검사 (1차):
        • 커널 모드에서 발생한 폴트인가? (커널 버그일 가능성, 또는 커널이 사용자 주소 접근 시)
        • fault_addr가 유효한 사용자 영역 주소인가? (is_user_vaddr()pml4_get_page()로 커널 매핑 확인 등)
      3. 현재 스레드의 보조 페이지 테이블(SPT) 조회:
        • struct page *page = spt_find_page(&thread_current()->spt, fault_addr) (가칭, vm/vm.c)
      4. 페이지가 SPT에 없는 경우 (Case 1: Invalid Access or Stack Growth):
        • 스택 확장 시도fault_addr가 현재 스택 포인터 근처이고, 유효한 스택 확장 범위 내인지 검사합니다. (예: fault_addr >= f->R.rsp - PUSH_SAVE_AREA 이고 fault_addr < USER_STACK 이고 USER_STACK - fault_addr <= MAX_STACK_SIZE)
          • Stack Growth:
            • vm_stack_growth(fault_addr) (가칭, vm/vm.c) 호출
            • 새로운 익명 페이지(VM_ANON)를 fault_addr에 해당하는 페이지 경계 주소로 SPT에 할당 (vm_alloc_page(VM_ANON, pg_round_down(fault_addr), true)).
            • vm_claim_page()를 통해 물리 프레임을 할당받고, SPT와 프레임을 연결하고, CPU 페이지 테이블(PML4)에 매핑합니다. 성공하면 page_fault() 핸들러 종료.
          • 스택 확장이 아니거나 실패하면, 잘못된 접근으로 간주하고 프로세스 종료 (exit(-1)).
      5. 페이지가 SPT에 있는 경우 (Case 2: Page needs to be loaded/swapped-in):
        • page 구조체에 있는 operations (함수 포인터 테이블)을 사용하여 해당 페이지 타입에 맞는 핸들러를 호출합니다.
        • vm_handle_fault(struct page *page, void *fault_addr, bool write, struct intr_frame *f) (가칭, vm/vm.c)
          • 이 함수는 page->operations->fault() (예: uninit_faultanon_faultfile_fault)를 호출할 수 있습니다.
          • 내부 로직 (예시 - uninit_fault 또는 file_fault의 일부):
            1. 물리 프레임 확보vm_get_frame() (가칭, vm/vm.c) 호출.
              • 만약 빈 프레임이 없다면, 페이지 교체 알고리즘(Page Replacement Algorithm) 실행 (vm_select_victim() 가칭).
              • 희생될 프레임(victim_frame)의 페이지(victim_page)가 dirty하면, victim_page->operations->swap_out(victim_page) 호출하여 디스크(스왑 또는 원본 파일)로 내보냄.
              • victim_frame을 정리 (PML4에서 매핑 해제, victim_page->frame = NULL).
            2. 프레임을 얻었으면(frame), page->frame = frame; frame->page = page; 연결.
            3. 데이터 로드:
              • VM_UNINIT 페이지: page->uninit.initializer(page, page->uninit.aux) 호출 (예: lazy_load_segment 실행).
              • VM_ANON (스왑된 경우): anon_swap_in(page, frame->kva) 호출.
              • VM_FILE (스왑 또는 처음 로드): file_backed_swap_in(page, frame->kva) 또는 파일에서 직접 읽기.
            4. CPU 페이지 테이블(PML4)에 매핑pml4_set_page(cur->pml4, page->va, frame->kva, page->writable) 호출.
            5. 성공적으로 처리되었으면 page_fault() 핸들러 종료.
      6. 폴트 유효성 검사 (2차 - 권한 등): 페이지가 이미 메모리에 있지만 쓰기 금지된 페이지에 쓰려고 했는지 (error_code & PTE_W) 등을 확인하여 처리. 실패 시 프로세스 종료.

3. 시스템 콜 (mmapmunmap)

  • syscall_handler() (userprog/syscall.c)
    • SYS_MMAP 요청 시:
      1. 인자 유효성 검사 (주소, 길이, fd 등).
      2. 요청된 가상 주소 범위(addr부터 addr + length)에 대해 루프를 돌면서 각 페이지(upage) 처리:
        • SPT에 이미 해당 upage가 있는지 확인 (겹치면 에러).
        • vm_alloc_page_with_initializer(VM_FILE, upage, writable, lazy_load_file_segment, file_info) (가칭) 호출하여 SPT에 파일 기반 미초기화 페이지로 등록. file_info에는 매핑할 파일, 오프셋, 읽을 바이트 수 등을 저장.
      3. 성공 시 매핑된 시작 주소(addr) 반환.
    • SYS_MUNMAP 요청 시:
      1. 인자 유효성 검사 (매핑 식별자 mapping).
      2. mapping에 해당하는 모든 페이지들을 SPT에서 찾아 루프:
        • struct page *page = spt_find_page(&thread_current()->spt, target_va);
        • 페이지의 destroy 함수 호출: page->operations->destroy(page) (예: file_backed_destroy).
          • file_backed_destroy 내부:
            • 페이지가 dirty하고 물리 프레임에 있다면, 파일에 변경 내용을 write-back. (file_write_at())
            • 물리 프레임이 할당되어 있다면 vm_free_frame(page->frame) 호출.
            • 페이지가 스왑 공간에 있다면 anon_free_slot() (만약 파일 기반 페이지도 스왑을 쓴다면) 호출.
        • SPT에서 해당 페이지 엔트리 제거.

4. 프로세스 종료 (process_exit)

  • process_exit() (userprog/process.c)
    • supplemental_page_table_kill(&thread_current()->spt) (가칭, vm/vm.c) 호출.
      • SPT를 순회하면서 각 struct page에 대해 page->operations->destroy(page) 호출하여 자원 해제 (mmap 해제, 스왑 슬롯 해제, 프레임 반납 등).
      • SPT 자체의 메모리도 해제.
    • pml4_destroy(curr->pml4): CPU의 페이지 테이블(PML4) 해제 (이 과정에서 프레임들도 해제될 수 있음).

5. 프레임 관리 및 페이지 교체 (Frame Management & Eviction)

  • vm_get_frame() (가칭, vm/vm.c): 새로운 물리 프레임을 요청할 때 호출됨 (주로 페이지 폴트 핸들러에서).
    1. palloc_get_page(PAL_USER)로 사용자 풀에서 프레임 할당 시도.
    2. 성공하면 해당 프레임을 프레임 테이블에 등록하고 반환.
    3. 실패하면 (물리 메모리 부족):
      • vm_evict_frame() 또는 vm_select_victim() (가칭) 호출하여 페이지 교체 알고리즘 실행.
        • 프레임 테이블을 순회하며 교체 대상 프레임(희생양, victim) 선택 (예: Clock 알고리즘).
        • Pinned된 프레임은 건너뜀.
      • 선택된 victim_frame에 연결된 victim_page를 처리:
        • CPU 페이지 테이블에서 victim_page의 매핑 제거 (pml4_clear_page()).
        • victim_page->operations->swap_out(victim_page) 호출하여 디스크로 내보내기. (dirty 비트 확인)
        • victim_page->frame = NULL; (연결 해제)
      • 이제 victim_frame은 비었으므로, 이 프레임을 현재 요청한 페이지를 위해 사용. 프레임 테이블 정보 업데이트 후 반환.
  • vm_free_frame(struct frame *frame) (가칭, vm/vm.c): 프레임이 더 이상 필요 없을 때 (예: 페이지가 destroy될 때).
    1. 프레임 테이블에서 해당 프레임 정보 제거 또는 상태 변경.
    2. palloc_free_page(frame->kva).

프로젝트 3의 핵심 기능들에 대한 대략적인 코드 흐름. 실제로 구현할 때는 include/vm/vm.h에 정의된 struct pagestruct framestruct page_operations 등의 자료구조를 중심으로 각 함수들을 채워나가기

특히 vm_alloc_page_with_initializervm_claim_pagespt_find_pagevm_handle_faultvm_get_frame, 페이지 타입별 initializerfaultswap_inswap_outdestroy 함수들이 주로 구현하게 될 부분

profile
개발 블로그 맞음.

0개의 댓글