[Pintos] - Virtual Memory - (Anonymous Page)

Junyeong Fred Kim·2022년 1월 20일
0

운영체제

목록 보기
19/27

Anonymous Page

  • 이 프로젝트에서는 non-disk 기반의 image인 anonymous page를 구현한다.
  • anonymous mapping에는 backing file이나 device가 없다.
  • file-backed pages와 달리 named file source가 없기 때문에 anonymous.
  • anonymous page는 stack과 heap같은 실행 파일에 사용된다.

include/vm/anon.hanon_page은 비어있지만, 구현할 때 필요한 정보나 상태를 저장하기 위해
추가할 수 있다.


Page Initialization with Lazy Loading

  • Lazy loading은 메모리 로드가 필요한 시점까지 지연시키는 설계
  • 해당 page struct가 있지만 전용 물리적 프레임이 없으며, 실제 페이지의 내용이 로드되지 않은 상태
  • 페이지 폴트가 발생하여 당장 필요해졌을 때 로드된다.
  1. 첫번째, 커널이 새 페이지 요청을 받으면 vm_alloc_page_with_initializer가 호출된다
    • initializer는 페이지 구조를 할당하고, 페이지 유형에 따라 적절한 initializer를 설정하여 새 페이지를 초기화하고 다시 사용자 프로그램으로 되돌린다.
  2. uninit_initialize가 호출되어 이전에 설정한 이니셜라이저를 호출한다.
    • initializer의 경우 anon_initializer, file-backed pages의 경우 file_backed_initializer가 된다.
  3. 페이지는 initialize->(page_fault->lazy-load->swap-in>swap-out->...)->destroy.의 라이프 사이클을 가질 수 있다.
    • 라이프 사이클이 전환될 때마다 페이지 유형(또는 VM_TYPE)에 따라 필요한 절차가 달라진다.

Lazy Loading for Executable

  • lazy loading에서는 프로세스가 실행을 시작하면, 즉시 필요한 메모리 부분만 메인 메모리에 로드된다. 이것은 binary image를 한 번에 메모리에 로드하는 eager loading에 비해 오버헤드를 줄일 수 있다.
  • lazy loading의 지원을 위해 include/vm/vm.hVM_UNINIT라는 페이지 유형을 도입.
    - 처음에는 모든 페이지가 VM_INIT 페이지로 생성된다.
  • 또한 uninitialized pages에 대한 페이지 구조 - include/vm/uninit.huninit_page를 제공한다.
    - creating, initialzing and destroying 관련 함수들은 include/vm/uninit.c에서 확인할 수 있다. (이 함수들 채워야 함)
    • 페이지 폴트 발생시, page fault는 제어를 vm/vm.cvm_try_handle_fault로 전달한다.
      • 여기서 유효한 페이지 폴트인지를 확인.
      • 유효한 페이지 폴트라는 것은 잘못된 접근을 하는 경우를 말한다.
  • bogus page fault의 오류는 세 가지 경우가 있다.
    - lazy-loaded, swaped-out page, wirte-protected page
    • 지금은 첫 번째 사례인 lazy-loaded page의 경우만 생각.
    • lazy loading을 위한 페이지 폴트인 경우 커널은 vm_alloc_page_with_initialzer에서 이전에 설정한 initializer 중 하나를 호출하여 segment를 lazy load한다.
    • userprog/process.clazy_load_segment를 구현해야 한다.

Implement vm_alloc_page_with_initializer(). You should fetch an appropriate initializer according to the passed vm_type and call uninit_new with it.


vm_alloc_page_with_initializer

bool vm_alloc_page_with_initializer (enum vm_type type, void *va,
        bool writable, vm_initializer *init, void *aux);
  • 주어진 타입에 따라 uninitialized page를 생성한다.
  • uninit page의 swap_in 핸들러는 타입에 따라 자동으로 초기화를 하고, AUX로 INIT을 호출한다.
  • 페이지 구성이 완료되면, 프로세스의 spt에 페이지를 삽입한다.
  • vm.h에 정의된 VM_TYPE 매크로를 사용하면 편리.

uninit_initialize

static bool uninit_initialize (struct page *page, void *kva);
  • 페이지 폴트 핸들러는 swap_in을 호출할 때, uninit_initailize에 도달한다.
  • 이미 모두 구현되어있다. 필요에 따라 uninit_initailize를 수정할 수 있다.
  • 또한, vm/anon.c에서 vm_anon_initanon_initializer를 수정할 수 있다.

vm_anon_init

void vm_anon_init (void);
  • anonymous page의 서브시스템으로 초기화를 한다.
  • anonymous page의 관련된 모든 것을 설정할 수 있다.

anon_initializer

bool anon_initializer (struct page *page,enum vm_type type, void *kva);
  • 이 함수는 먼저 page->operations 연산을 통해 anonymous page 핸들러를 설정한다.
  • 빈 구조인 anon_page에서 일부 정보 업데이트 필요할 수 있다.
  • 이 함수는 anonymous pages(i.e. VM_ANON)의 initializer로 사용된다.

userprog/process.c에서 load_segmentlazy_load_segment를 구현해야한다.

load_segment, lazy_load_segment

  • 실행 파일로부터 segment를 적재하는 기능 구현
  • 이 페이지들은 커널이 페이지 폴트를 가로채는 경우에만 로드
    - lazy loading
  • userprog/process.c를 변경
  • 루프를 돌 때마다 vm_alloc_page_with_initializer를 불러서 pending page object를 생성
    - 페이지 폴트 발생시 세그먼트 실제로 로드

load_segment

static bool load_segment (struct file *file, off_t ofs, uint8_t *upage,
        uint32_t read_bytes, uint32_t zero_bytes, bool writable);
  • vm_alloc_page_with_initializer를 호출하여 aux argument를 설정
  • binary loading 시, 구조체를 생성하여 필요한 정보를 포함할 수 있다.

lazy_load_segment

static bool lazy_load_segment (struct page *page, void *aux);
  • load_segment에서 lazy_load_segment가 vm_alloc_page_with_initializer의 네 번째 인수로 제공된다.
  • 이 함수는 실행 파일 페이지를 위한 초기화 함수이며, page fault시에 실행된다.
  • page 구조체와 aux를 인자로 받는다.
  • aux는 load_segment에서 설정하는 정보이며, 이 정보를 이용하여 세그먼트를 채울 파일을 찾아서 읽어온다.

setup_stack

  • stack할당을 새 메모리 관리 시스템에 맞추려면 setup_stack을 조정해야 한다.
  • 첫 번째 stack page를 lazy하게 할당할 필요는 없다.
    - 오류 발생까지 기다릴 필요없이 load시 command line arguments를 사용하여 할당하고 초기화할 수 있다.
  • 스택을 식별할 수 있도록 vm/vm.h vm_type (e.g. VM_MARKER_0)의 aux markers를 사용하여 표시해야한다.

vm_try_handle_fault

  • vm_try_handle_fault 함수를 수정하고, spt_find_page를 통해 페이지 폴트가 발생한 주소에 해당하는 page structure를 얻어와 페이지 폴트를 해결해야 한다.
  • 모두 구현하면, fork를 제외한 project2의 모든 테스트는 통과되어야 한다.

Supplemental Page Table - Revisit

  • 자식 프로세스 생성 또는 프로세스 제거를 할 때 copy와 clean up 기능이 각각 필요하다.
  • supplemental page table을 다시 방문하는 이유는 구현한 초기화 기능 중 일부를 사용할 수도 있기 때문.

Implement supplemental_page_table_copy and supplemental_page_table_kill in vm/vm.c.

supplemental_page_table_copy

bool supplemental_page_table_copy (struct supplemental_page_table *dst,
    struct supplemental_page_table *src);

supplemental_page_table_kill

void supplemental_page_table_kill (struct supplemental_page_table *spt);

Page Cleanup

작성 중

profile
기억보다 기록

0개의 댓글