정글 일지
[Pintos_project3 (8)] vm_get_frame, vm_evict_frame, vm_get_victim
미뿌감
2024. 11. 30. 21:09
728x90
1. 개요
페이지와 PF을 연결시키는 함수를 구현해야 한다.
2. 본문
// vm/vm.c
/* palloc() and get frame. If there is no available page, evict the page
* and return it. This always return valid address. That is, if the user pool
* memory is full, this function evicts the frame to get the available memory
* space.
* palloc()을 사용하여 프레임을 할당. 만약 사용할 수 있는 페이지가 없다면, 페이지를 교체하여 프레임을 반환.
* 이 함수는 항상 유효한 주소를 반환해야 한다.
* if, 사용자 풀 메모리가 가득 찬 경우 -> vm_evict_frame을 이용해서 사용 가능한 메모리 공간을 확보
*/
static struct frame *
vm_get_frame (void) {
/* TODO: Fill this function. */
/* pseudo code
* 남은 메모리가 있는지 확인
* (남아있다면) lazy_load_segment를 호출하면 되는거 아닌가?
* (남아있지 않다면) vm_evict_frame을 호출하고, lazy_load_segment */
struct frame *frame = (struct frame *)malloc(sizeof(struct frame));
ASSERT(frame != NULL);
frame->kva = palloc_get_page(PAL_USER | PAL_ZERO); // 유저 풀(PM)에서 페이지를 할당 받음. 또한, 할당 받은 페이지를 0으로 선언.
if (frame->kva == NULL)
frame = vm_evict_frame(); // swap out 실행
else
list_push_back(&frame_table, &frame->frame_elem); // frame 구조체에 frame_elem 추가.
frame->page = NULL; // 현 시점에는, 아직 page랑 연결된 게 아니므로, 명시적으로 NULL을 넣어주어 이를 표현해준다.
ASSERT (frame->page == NULL);
return frame;
}
vm_get_frame 함수에서, palloc_get_page를 해보고, 만약 NULL이라면, 페이지 할당에 실패된 것이므로 vm_evict_frame()을 호출해 주었다.
NULL이 아니라면 페이지 할당에 성공한 것이므로, frame_table에 해당 frame_elem을 뒤에다가 넣어주었다.
// vm/vm.c
/* Evict one page and return the corresponding frame.
* Return NULL on error.*/
static struct frame *
vm_evict_frame (void) {
struct frame *victim UNUSED = vm_get_victim (); // 제거할 프레임을 선택하는 함수 vm_get_victim ^
/* TODO: swap out the victim and return the evicted frame. */
/* Pseudo code: 선언했던 frame_table에서, 제일 앞에 있는 frame 주소를 반환? */
if (victim->page) // 해당 프레임에 페이지가 연결되어 있다면 swap_out을 시킨다. - 디스크의 swap 영역으로 보내는 함수.
swap_out(victim->page);
return victim;
}
vm_get_victim()을 호출에서 제거할 프레임을 선택해 준다.
만약, 이전에 해당 프레임에 연결되어 있는 페이지가 있다면, swap_out 함수를 호출해서 페이지를 배척해준다.
이후, 새로운 값을 할당할 frame을 반환해 준다.
/* Get the struct frame, that will be evicted. 제거할 프레임을 넘기는 것.*/
static struct frame *
vm_get_victim (void) {
struct frame *victim = NULL;
/* TODO: The policy for eviction is up to you. */
struct thread *curr = thread_current();
struct list_elem *e = list_begin(&frame_table);
for (e; e != list_end(&frame_table); e = list_next(e)) {
victim = list_entry(e, struct frame, frame_elem);
if (pml4_is_accessed(curr->pml4, victim->page->va))
pml4_set_accessed(curr->pml4, victim->page->va, false);
else
return victim;
}
return list_entry(list_begin(&frame_table), struct frame, frame_elem);
}
vm_get_victim을 통해서, 오랫동안 사용하지 않은 frame을 대상으로 선택하고자 한다.
만약, 대상이 되는 frame이 없다면, list의 맨 앞에 있는 frame을 대상으로 evict를 해주었다.
마지막으로 vm_init함수에서 list_init을 통해 frame_table을 초기화 해주어야 한다.
// vm/vm.c
/* Initializes the virtual memory subsystem by invoking each subsystem's
* intialize codes. */
void
vm_init (void) {
vm_anon_init (); // 시스템 부팅 시 호출. VM과 관련된 설정
vm_file_init (); // 시스템 부팅 시 호출. VM과 관련된 설정
#ifdef EFILESYS /* For project 4 */
pagecache_init ();
#endif
register_inspect_intr ();
/* DO NOT MODIFY UPPER LINES. */
/* TODO: Your code goes here. */
list_init(&frame_table); //****** 요기 추가
}
3. 결과
아직은 123 failed이다.
728x90