미소를뿌리는감자의 코딩
[Pintos_project3 (12)] supplemental_page_table_copy, supplemental_page_table_kill 본문
[Pintos_project3 (12)] supplemental_page_table_copy, supplemental_page_table_kill
미뿌감 2024. 12. 2. 23:001. 개요
이번에는 supplemental_page_table_copy와 supplemental_page_table_kill에 대해서 알아보려 한다.
supplemental_page_table_copy는 자식 프로세스가 부모 프로세스의 context를 상속할 때, 즉, fork()할 때 사용된다.
만약 UNINIT페이지라면, 즉시 eager로 페이지 할당을 진행하고, 복사를 진행한다.
supplemental_page_table_kill의 경우엔, 프로세스 파괴시, thread에서 사용 중인 spt element를 찾고 이에 대해서 free를 해준다.
2. 본문
supplemental_page_table_copy 코드는 아래와 같다.
// vm/vm.c
/* Copy supplemental page table from src to dst */
bool
supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED,
struct supplemental_page_table *src UNUSED) {
/* pseudo
* spt를 순회하면서, UNINIT상태인지 확인
* UNINIT상태라면, vm_do_claim_page를 eager로 함.
*/
struct hash_iterator iter;
struct page *dst_page;
struct aux *aux;
hash_first(&iter, &src->spt_hash);
while(hash_next(&iter)) { //spt 순환
struct page *src_page = hash_entry(hash_cur(&iter), struct page, hash_elem);
enum vm_type type = src_page->operations->type;
void *upage = src_page->va;
bool writable = src_page->writable;
switch (type) {
case VM_UNINIT: //vm_alloc_page_with_initializer로 새로운 spt에 페이지 할당.
if (!vm_alloc_page_with_initializer(page_get_type(src_page), upage, writable, src_page->uninit.init, src_page->uninit.aux))
goto err;
break;
case VM_FILE:
if(!vm_alloc_page_with_initializer(type, upage, writable, NULL, &src_page->file))
goto err;
dst_page = spt_find_page(dst, upage);
if(!file_backed_initializer(dst_page, type, NULL))
goto err;
dst_page->frame = src_page->frame;
if(!pml4_set_page(thread_current()->pml4, dst_page->va, src_page->frame->kva, src_page->writable))
goto err;
break;
case VM_ANON:
if(!vm_alloc_page(type, upage, writable))
goto err;
break;
default:
goto err;
}
}
return true;
err:
return false;
}
다음으로 supplemental_page_table_kill에 대해서 알아보자.
/* Free the resource hold by the supplemental page table */
void
supplemental_page_table_kill (struct supplemental_page_table *spt UNUSED) {
/* TODO: Destroy all the supplemental_page_table hold by thread and
* TODO: writeback all the modified contents to the storage. */
/* pseudo:
* thread에서 사용 중이라고 mark되어 있는 spt element를 찾고 이에 대해서, free를 해줌. */
hash_clear(&spt->spt_hash, hash_destructor); // hash_clear 함수 호출
}
spt->spt_hash에서 각각의 element에 대해서 hash_destructor 함수를 적용시켜 준다.
// lib/kernel/hash.c
/* hash의 모든 요소 제거 spt->spt_hash를 전달했다면 이를 모두 제거.
* DESTRUCTOR가 null이면, H에 있는 각 요소에 대해서 DESTRUCTOR가 호출
* hash_clear가 호출되는 동안, hash_clear, hash_destory(), hash_insert()가 호출되면 문제를 일으킬 수 있음
* (destructor가 NULL) -> hash_table의 모든 요소는 제거하지만 요소의 메모리는 free하지 않음.
* (!destructor가 NULL) -> 메모리 해제*/
void
hash_clear (struct hash *h, hash_action_func *destructor) {
size_t i;
for (i = 0; i < h->bucket_cnt; i++) {
struct list *bucket = &h->buckets[i];
if (destructor != NULL) // hash_table을 순환하면서, 각각의 elem에 대해 destructor 함수 호출.
while (!list_empty (bucket)) {
struct list_elem *list_elem = list_pop_front (bucket);
struct hash_elem *hash_elem = list_elem_to_hash_elem (list_elem);
destructor (hash_elem, h->aux);
}
list_init (bucket);
}
h->elem_cnt = 0;
}
이는 hash_table에서 각각의 elem을 순환하면서 destructor 함수를 호출해주는 함수이다.
supplemental_page_table_kill에서는 hash_destructor 함수를 호출하였다.
hash_destructor의 경우엔 lib/kernel/hash.c에 정의해 주었다. - hash.h에서 선언하였다.
// lib/kernel/hash.c
void hash_destructor(struct hash_elem *e, void *aux) {
const struct page *p = hash_entry(e, struct page, hash_elem); // hash_elem을 포함하고 있는 페이지를 반환해주는 함수.
destroy(p);
free(p);
}
hash_entry로 hash_elem을 포함하고 있는 페이지를 찾고 이에 대해서 destory 후, free 해주었다.
destroy의 경우엔 vm.h에서 page_operations에 정의되어 있다.
3. 결과
54 of 141 tests failed 로 2개가 더 통과한 것을 확인할 수 있다.
'정글 일지' 카테고리의 다른 글
[Pintos_project3 (14)] vm_try_handle_fault, vm_stack_growth (0) | 2024.12.03 |
---|---|
[Pintos_project3 (13)] uninit_destory, anon_destory (0) | 2024.12.02 |
[Pintos_project3 (11)] vm_try_handle_fault (0) | 2024.12.02 |
[Pintos_project3 (10)] vm_anon_init, setup_stack (0) | 2024.12.02 |
[Pintos_project3 (9)] vm_claim_page, vm_do_claim_page (0) | 2024.12.02 |