거북이의 쉼터

(2022.02.27) Anonymous Page 가이드라인 (1) 본문

코딩 삽질/KAIST PINTOS (CS330)

(2022.02.27) Anonymous Page 가이드라인 (1)

onlim 2022. 2. 27. 22:08

저녁 먹고 돌아왔다. Anonymous Page의 매뉴얼을 읽어보자.

 

매뉴얼에 쓰여진 주된 사항은 anon.c의 코드를 수정하라는 것이다. VM_ANON 타입의 페이지는 이전 포스팅에서 언급한대로, 파일에서 기원하지 않은 모든 페이지, 즉 대다수의 페이지를 차지한다. 현재 실행되고 있는 프로세스의 내용, stack 등은 전부 VM_ANON 타입의 페이지로 메모리에서 관리된다.

 

그래서 구현해야 할 사항이 무엇인가 하고 봤다. 바로 Lazy Loading이 나온다. 지난 번에 언급했듯이 프로젝트 2까지 pintos는 전부 eager loading, 즉 페이지를 요청하자마자 페이지를 할당하여 내용을 채우고 반환하는 짓을 해왔다. 그러나 지금부터는 페이지를 요청한 뒤, 직접적으로 접근이 일어나기 전까지는 페이지를 할당하지 않도록 구현하라는 것이다. 이걸 위해 vm_alloc_page_with_initializer를 통해 우선 "임시 매핑"을 만들어 놓은 뒤 page fault가 일어날 때 실질적으로 할당과 매핑이 일어나도록 구성하도록 한다. 

 

매뉴얼에서는 page fault를 valid와 bogus로 구분한다. valid는 정말 invalid한 주소에 접근하려고 해서 프로세스를 터뜨려야 하는 경우이며, bogus의 경우에는 몇 개의 작업을 통해 프로세스를 정상 궤도로 올려놓을 수 있는 경우이다. bogus의 경우 다시 3가지로 구분할 수 있는데, 

 

  1. lazy-loaded 페이지에 접근
  2. swaped-out 페이지에 접근
  3. write-protected 페이지에 쓰기 권한 접근

3은 Copy-on-Write(Extra) 구현 전까지는 계속 valid page-fault일 것이니 일단은 1, 2에 집중할 것이다. 그리고 심지어 일단은 1에만 집중하란다.

 

우선 lazy loading을 위해 기본적으로 구현해야 하는 함수는 아래와 같다.

bool vm_alloc_page_with_initializer (enum vm_type type, void *va, bool writable, vm_initializer *init, void *aux);
static bool uninit_initialize (struct page *page, void *kva);

이 함수들은 앞선 포스팅에서도 설명했으니 넘어간다.

 

VM_ANON 타입의 lazy loading을 위해 구현할 부가적인 함수는

void vm_anon_init (void);
bool anon_initializer (struct page *page, enum vm_type type, void *kva);

위의 2개이다. 두 함수의 차이는 vm_anon_init의 경우 VM_ANON 타입의 페이지 전체를 위해 initialize 해야 하는 것들을 해 주는 함수이다. 예를 들어 swap 공간을 생성하고 초기화하는 것이 있다. 예라고 해 봤자 지금은 그거밖에 안보이지만.. anon_initializer는 주어진 페이지 자체에 대한 initialization인 것 같은데 uninit_initialize에서 해당 페이지에 대한 initialize를 진행할 때 불려야 하는 함수 같다. 일단 VM_UNINIT 타입의 페이지를 VM_ANON으로 바꿔주는 것만 진행하면 될 것 같다. swap in/out을 구현할 때 swapping에 필요한 추가 멤버가 있어서 이후에는 해당 멤버도 초기화시켜 주어야 할 것 같다. 일단 나중에 생각한다.

 

위에서 구현된 함수를 사용해서 프로젝트 3~4에 사용될 load_segment를 구현해야 한다. 프로젝트 2까지는 lazy load를 사용하지 않는 load_segment가 구현되어 있었고, load는 해당 함수를 사용했으나, 이제는 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);
static bool lazy_load_segment (struct page *page, void *aux);

load_segment에서 일단 vm_alloc_page_with_initializer를 통해 VM_UNINIT 타입의 페이지를 생성해 놓은 뒤, 후에 page_fault로 initialize가 될 때 lazy_load_segment로 initialize를 하는 방식이다. argument passing이 이루어지는 첫 번째 stack page는 eager loading을 허용한다고 매뉴얼에 나오니 참고한다.

 

마지막으로 vm_try_handle_fault을 구현해서 page fault를 핸들링하도록 하면 우선 첫 번째 milestone에 도착한다. 여기까지 제대로 구현했다고 하면 fork를 제외한 나머지 프로젝트 2가 돌아가야 한다고 한다.

 

우선 여기까지 구현하는 것을 목적으로 하고 구현을 해 보자. 그래도 많아...

Comments