
2025.06.05
오늘한 내용 : PintOS - Project3: Virtual Memory - Lazy Load & anonymous page 구현!
WEEK 12 : 정글 끝까지(PintOS) - Virtual Memory
4. 파일 기반 페이즈(Lazy Load) 구현 (
userprog/process.c+vm/vm.c)
load_segment()에서 “실행 파일의 코드/데이터를 한 번에 메모리에 올리는 대신, 페이지 단위로 SPT 예약만” 하도록 바꿉니다.
- 디스크 ↔ 물리 메모리 사이의 Lazy load
lazy_load_segment()에서 실제로 할당
- (이 단계까지 완료해야 Project 2의 lazy-loading 테스트가 통과됩니다.)
- load_segment(), lazy_load_segment() 구현
process.c
-----------------------
static bool
load_segment(struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes, bool writable)
{
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
ASSERT(pg_ofs(upage) == 0);
ASSERT(ofs % PGSIZE == 0);
while (read_bytes > 0 || zero_bytes > 0)
{
/* Do calculate how to fill this page.
* We will read PAGE_READ_BYTES bytes from FILE
* and zero the final PAGE_ZERO_BYTES bytes. */
size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
size_t page_zero_bytes = PGSIZE - page_read_bytes;
/* TODO: Set up aux to pass information to the lazy_load_segment. */
/* 로드를 위해 필요한 정보를 가진 load_info 구조체 만들었음*/
struct load_info *aux = (struct load_info *)malloc(sizeof(*aux));
if (aux == NULL)
return false;
aux->file = file;
aux->offset = ofs;
aux->read_bytes = page_read_bytes;
aux->zero_bytes = page_zero_bytes;
if (!vm_alloc_page_with_initializer(VM_ANON, upage,
writable, lazy_load_segment, aux))
{
free(aux);
return false;
}
/* Advance. */
/* 4) 다음 반복을 위해 각 값 갱신 */
read_bytes -= page_read_bytes;
zero_bytes -= page_zero_bytes;
upage += PGSIZE;
/* 파일에서 연속적으로 다음 페이지를 읽어 오기 위함 */
ofs += page_read_bytes; /* ofs를 읽어들인 만큼만 증가 */
}
return true;
}
-----------------------------
static bool
lazy_load_segment(struct page *page, void *aux)
{
/* TODO: Load the segment from the file */
/* TODO: This called when the first page fault occurs on address VA. */
/* TODO: VA is available when calling this function. */
struct load_info *info = (struct load_info *)aux;
struct file *file = info->file;
off_t offset = info->offset;
uint32_t read_bytes = info->read_bytes;
uint32_t zero_bytes = info->zero_bytes;
/* 1) 이미 페이지에 매핑된 frame을 준비함 */
struct frame *frame = page->frame;
if (frame == NULL)
{
free(info);
return false;
}
void *kva = frame->kva;
/* 2) 파일 위치 설정 후, read_bytes만큼 읽어서 kva에 복사 */
file_seek(file, offset);
if (file_read(file, kva, read_bytes) != (int)read_bytes)
{
free(info);
return false;
}
/* 3) 나머지 부분(zero_bytes)만큼 0으로 채움 */
memset(kva + read_bytes, 0, zero_bytes);
free(info);
return true;
}
/* Create a PAGE of stack at the USER_STACK. Return true on success. */
static bool
setup_stack(struct intr_frame *if_)
{
bool success = false;
void *stack_bottom = (void *)(((uint8_t *)USER_STACK) - PGSIZE);
/* TODO: Map the stack on stack_bottom and claim the page immediately.
* TODO: If success, set the rsp accordingly.
* TODO: You should mark the page is stack. */
/* TODO: Your code goes here */
/* ANON 스택 페이지 하나 할당 받음
writable : true
*/
if (!vm_alloc_page(VM_ANON, stack_bottom, true))
return false;
// 할당 받은 페이지에 바로 물리 프레임을 매핑한다.
if (!vm_claim_page(stack_bottom))
return false;
// rsp를 변경한다. (argument_stack에서 이 위치부터 인자를 push한다.)
if_->rsp = USER_STACK;
success = true;
return success;
}
(Process exit codes are excluded for matching purposes.)
pass tests/userprog/args-none
pass tests/userprog/args-single
pass tests/userprog/args-multiple
pass tests/userprog/args-many
pass tests/userprog/args-dbl-space
pass tests/userprog/halt
pass tests/userprog/exit
pass tests/userprog/create-normal
pass tests/userprog/create-empty
pass tests/userprog/create-null
pass tests/userprog/create-bad-ptr
pass tests/userprog/create-long
pass tests/userprog/create-exists
pass tests/userprog/create-bound
pass tests/userprog/open-normal
pass tests/userprog/open-missing
pass tests/userprog/open-boundary
pass tests/userprog/open-empty
pass tests/userprog/open-null
pass tests/userprog/open-bad-ptr
pass tests/userprog/open-twice
pass tests/userprog/close-normal
pass tests/userprog/close-twice
pass tests/userprog/close-bad-fd
pass tests/userprog/read-normal
pass tests/userprog/read-bad-ptr
FAIL tests/userprog/read-boundary
pass tests/userprog/read-zero
pass tests/userprog/read-stdout
pass tests/userprog/read-bad-fd
pass tests/userprog/write-normal
pass tests/userprog/write-bad-ptr
pass tests/userprog/write-boundary
pass tests/userprog/write-zero
pass tests/userprog/write-stdin
pass tests/userprog/write-bad-fd
FAIL tests/userprog/fork-once
FAIL tests/userprog/fork-multiple
FAIL tests/userprog/fork-recursive
FAIL tests/userprog/fork-read
FAIL tests/userprog/fork-close
FAIL tests/userprog/fork-boundary
FAIL tests/userprog/exec-once
FAIL tests/userprog/exec-arg
FAIL tests/userprog/exec-boundary
pass tests/userprog/exec-missing
pass tests/userprog/exec-bad-ptr
FAIL tests/userprog/exec-read
FAIL tests/userprog/wait-simple
FAIL tests/userprog/wait-twice
FAIL tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
FAIL tests/userprog/multi-recurse
FAIL tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
FAIL tests/userprog/rox-child
FAIL tests/userprog/rox-multichild
pass tests/userprog/bad-read
pass tests/userprog/bad-write
pass tests/userprog/bad-read2
pass tests/userprog/bad-write2
pass tests/userprog/bad-jump
pass tests/userprog/bad-jump2
FAIL tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
FAIL tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
FAIL tests/vm/pt-write-code
FAIL tests/vm/pt-write-code2
FAIL tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
FAIL tests/vm/page-parallel
FAIL tests/vm/page-merge-seq
FAIL tests/vm/page-merge-par
FAIL tests/vm/page-merge-stk
FAIL tests/vm/page-merge-mm
pass tests/vm/page-shuffle
FAIL tests/vm/mmap-read
FAIL tests/vm/mmap-close
FAIL tests/vm/mmap-unmap
FAIL tests/vm/mmap-overlap
FAIL tests/vm/mmap-twice
FAIL tests/vm/mmap-write
FAIL tests/vm/mmap-ro
FAIL tests/vm/mmap-exit
FAIL tests/vm/mmap-shuffle
pass tests/vm/mmap-bad-fd
FAIL tests/vm/mmap-clean
FAIL tests/vm/mmap-inherit
FAIL tests/vm/mmap-misalign
FAIL tests/vm/mmap-null
FAIL tests/vm/mmap-over-code
FAIL tests/vm/mmap-over-data
FAIL tests/vm/mmap-over-stk
FAIL tests/vm/mmap-remove
pass tests/vm/mmap-zero
pass tests/vm/mmap-bad-fd2
pass tests/vm/mmap-bad-fd3
pass tests/vm/mmap-zero-len
FAIL tests/vm/mmap-off
FAIL tests/vm/mmap-bad-off
FAIL tests/vm/mmap-kernel
FAIL tests/vm/lazy-file
pass tests/vm/lazy-anon
FAIL tests/vm/swap-file
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
FAIL tests/vm/swap-fork
pass tests/filesys/base/lg-create
pass tests/filesys/base/lg-full
pass tests/filesys/base/lg-random
pass tests/filesys/base/lg-seq-block
pass tests/filesys/base/lg-seq-random
pass tests/filesys/base/sm-create
pass tests/filesys/base/sm-full
pass tests/filesys/base/sm-random
pass tests/filesys/base/sm-seq-block
pass tests/filesys/base/sm-seq-random
FAIL tests/filesys/base/syn-read
pass tests/filesys/base/syn-remove
FAIL tests/filesys/base/syn-write
pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
pass tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
pass tests/threads/priority-change
pass tests/threads/priority-donate-one
pass tests/threads/priority-donate-multiple
pass tests/threads/priority-donate-multiple2
pass tests/threads/priority-donate-nest
pass tests/threads/priority-donate-sema
pass tests/threads/priority-donate-lower
pass tests/threads/priority-fifo
pass tests/threads/priority-preempt
pass tests/threads/priority-sema
pass tests/threads/priority-condvar
pass tests/threads/priority-donate-chain
FAIL tests/vm/cow/cow-simple
56 of 141 tests failed.
spt_copy, kill 작성하면 fork 관련 함수들까지 다 통과한다고 한다..
자잘한것들도 많이 고쳐야 되겠다..