Project 3 : Virtual Memory - Stack Growth (기입완료-수정중)

Stack Growth

프로젝트 2에서 스택은 USER_STACK에서 시작하는 단일 페이지였으며, 프로그램 실행은 이 크기로 제한되었습니다. 이제 스택이 현재 크기 이상으로 커지면 필요에 따라 추가 페이지를 할당합니다.

 

스택 액세스로 '보이는' 경우에만 추가 페이지를 할당합니다. 스택 액세스와 다른 액세스를 구별하는 휴리스틱(heuristic- cs에서는 발견법 정도로 생각하면 될듯) 을 고안합니다.

 

사용자 프로그램이 스택 포인터 아래의 스택에 쓰면 버그(User programs are buggy if they write to the stack below the stack pointer) 가 발생합니다. 일반적인 실제 OS는 스택의 데이터를 수정하는 '신호'를 전달하기 위해 언제든지 프로세스를 중단할 수 있기 때문입니다. 그러나 x86-64 PUSH 명령어는 스택 포인터를 조정하기 전에 액세스 권한을 확인하므로 스택 포인터 8바이트 아래에서 page fault 가 발생할 수 있습니다.

 

사용자 프로그램의 스택 포인터의 현재 값을 얻을 수 있어야 합니다. 시스템 호출 또는 사용자 프로그램에 의해 생성된 page fault 내에서 각각 syscall_handler() 또는 page_fault()로 전달된 구조체 intr_frame의 rsp 멤버에서 해당 값(the current value of the user programs's stack pointer) 을 검색할 수 있습니다. 유효하지 않은 메모리 액세스를 감지하기 위해 page faults에 의존하는 경우 커널에서 page faults이 발생하는 다른 경우를 처리해야 합니다. 프로세서는 예외로 인해 사용자 모드에서 커널 모드로 전환될 때만 스택 포인터를 저장하므로, page_fault()로 전달된 구조체 intr_frame에서 rsp를 읽으면 사용자 스택 포인터가 아닌 정의되지 않은 값이 반환됩니다. 사용자 모드에서 커널 모드로 처음 전환할 때 struct thread에 rsp를 저장하는 등 다른 방법을 마련해야 합니다.

 

stack growth 기능을 구현합니다. 이를 구현하려면 먼저 vm/vm.c에서 vm_try_handle_fault를 수정하여 stack growth를 식별합니다. stack growth를 식별한 후에는 vm/vm.c에서 vm_stack_growth를 호출하여 스택을 증가시켜야 합니다. vm_stack_growth를 구현하세요.

 

bool vm_try_handle_fault (struct intr_frame *f, void *addr,
    bool user, bool write, bool not_present);

-이 함수는 페이지 오류 예외를 처리하는 동안 userprog/exception.c의 page_fault에서 호출됩니다. 이 함수에서는 page fault stack growth에 유효한 경우인지 여부를 확인해야 합니다. stack growth로 오류를 처리할 수 있음을 확인했다면 오류가 발생한 주소로 vm_stack_growth를 호출합니다.

 

void vm_stack_growth (void *addr);

-addr가 더 이상 결함이 있는 주소가 되지 않도록 하나 이상의 anonymous pages를 할당하여 스택 크기를 늘립니다. 할당을 처리할 때 addr을 PGSIZE로 내림해야 합니다.

 

대부분의 OS는 스택 크기에 절대적인 제한을 두고 있습니다. 일부 OS에서는 사용자가 제한을 조정할 수 있습니다(예: 많은 Unix 시스템에서 ulimit 명령). 많은 GNU/Linux 시스템에서 기본 제한은 8MB입니다. 이 프로젝트의 경우 스택 크기를 최대 1MB로 제한해야 합니다.

이제 모든 스택 증가 테스트 케이스가 통과되어야 합니다.

 

  Comments,     Trackbacks