참고로 이번 TIL에는 놀러간 이야기와 사진들이 많습니다!
[목표]
stack growth를 구현하고 관련 테스트 케이스를 통과해봅니다. (진행중)
놀러가기때문에, 가서 시간 남는대로 티스토리 정리해봅니다.
벨로그와 노션 먼저 정리하기. 틈틈히 코드 관련 해서 정리하기.
밀린 티스토리정리하기!!!!!!! (너무 밀림)
출근해서 잤음… 5시에 여파가…
stack growth를 구현해봅니다.
먼저 vm_try_handle_fault 함수를 수정해줘야한다. 왜냐하면 스택 자동확장이 필요한 시기에 확장을 시도해야하기 때문입니다. 즉, 스택 증가를 식별해줍니다. 케이스1과 2가 정상적으로 실행된다면 페이지 적재를 수행합니다.
/* Return true on success */
// 성공 시 true를 반환합니다.
bool
vm_try_handle_fault (struct intr_frame *f UNUSED, void *addr UNUSED,
bool user UNUSED, bool write UNUSED, bool not_present UNUSED) {
struct supplemental_page_table *spt UNUSED = &thread_current ()->spt;
struct page *page = spt_find_page(spt, addr); /* valid address인지 확인 */
void *va = pg_round_down(addr); // 주소를 정렬에 맞춰준다.
/* TODO: Validate the fault */
/* TODO: Your code goes here */
// case 1: page가 없음 → stack growth 고려
// 스택 자동확장이 필요한 상황일 때, vm_stack_growth 함수로 확장해줍니다.
if(page == NULL) {
// 유저 모드에서 발생한 폴트만 처리, 유저 스택 포인터 바로 아래에 접근할 시 허용, 접근한 주소가 전체 유저 스택 범위 안에 있는지 확인. -> 모든 조건일시 스택 확장
// 스택확장 부분이 왜 if문에 있는지 의아할 수 있는데, 이는 스택확장이 무조건 성공하지 않으므로 실패시 spt_find_page를 실행하지 않도록 방지한다.
if (user && addr >= f->rsp - 32 && addr < USER_STACK && vm_stack_growth(addr)) {
page = spt_find_page(spt, addr); // addr이 현재 스택 영역 바로 아래에 접근한 경우에만 새 페이지를 할당
}
else
return false;
}
// case 2: 접근 권한 확인 (write 접근인데 read-only면 실패)
if (write && !page->writable) // 쓰기 접근인데 페이지가 읽기 전용이라면, false 반환
return false;
// 페이지 적재 (uninit이든 아니든 모두 처리)
return vm_do_claim_page (page);
}
vm_stack_growth 를 구현하다가 가족행사로 인해 나왔습니다.
모든 내용 티스토리와 벨로그 동기화 완료.
놀랍게도 다음과 같이 구현하면 테스트 케이스가 통과된다. 아마 페이지 폴트에서 넘기는 부분에서 미리 구현해서 그런 것 같다. 이유는 정글에서 적어보겠다.
tests/vm/pt-grow-stack 와 tests/vm/pt-big-stk-obj 두가지 테스트 케이스이다.
/* Growing the stack. */
// 스택을 키웁니다.
static bool
vm_stack_growth (void *addr UNUSED) {
struct thread *t = thread_current();
void *va = pg_round_down(addr); // 주소를 정렬에 맞춰준다.
// 실제로 할당 요청
return vm_alloc_page(VM_ANON | VM_MARKER_0, va, true);
}
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
pass 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
pass tests/userprog/fork-once
pass tests/userprog/fork-multiple
pass tests/userprog/fork-recursive
FAIL tests/userprog/fork-read
FAIL tests/userprog/fork-close
FAIL tests/userprog/fork-boundary
pass tests/userprog/exec-once
pass 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
pass tests/userprog/wait-simple
pass tests/userprog/wait-twice
pass tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
pass tests/userprog/multi-recurse
pass tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
pass tests/userprog/rox-child
pass 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
pass tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
pass tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
pass tests/vm/pt-write-code
FAIL tests/vm/pt-write-code2
FAIL tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
pass 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
39 of 141 tests failed.




[목표]
stack growth를 구현하고 관련 테스트 케이스를 통과해봅니다.



팔순잔치를 마치고 복귀했다.
새로운 시놀로지 패키지가 있어서 시놀로지에 들어가 패키지를 살펴보았다.
예전에 대학교때 진행한 프로젝트가 리포지트리에 없어서 정글에서 배운대로 클론해서 내 리포지트리에 추가했다.
스택 그로우를 어제 완성했지만, 이해하지 못해 이해하며 통과하지 못한 테스트 케이스를 확인해보고 있다.
각각의 결과값을 확인하면서 부족한 부분을 수정해보고 있다.
FAIL tests/userprog/fork-read
FAIL tests/userprog/fork-close
FAIL tests/userprog/fork-boundary
FAIL tests/userprog/exec-boundary
FAIL tests/userprog/exec-read
FAIL tests/vm/pt-write-code2
FAIL tests/vm/pt-grow-stk-sc
FAIL tests/vm/page-merge-seq
FAIL tests/vm/page-merge-par
FAIL tests/vm/page-merge-stk
FAIL tests/vm/page-merge-mm
권호형이 디버깅하는 방법을 보여줬습니다. 아직까지 저에겐 디버깅 실력이 부족한 것 같습니다. 해당 트러블 슈팅은 같이 해결해보았습니다. (사실 권호형이 다함)
테스트 케이스에는 msg를 통해 어디까지 테스트가 통과하는지 살펴보고 코드안에서는(do__fork 등) printf를 통해 어디부분에서 넘어가지 않는지 분석해보았습니다.
그 결과 src_page와 dst_page를 찍어보았는데, src_page가 제대로 찍히지 않았습니다. 페이지 type을 잘 걸러내지 못한 것으로 생각되어 if문의 type을 다음과 같이 수정했습니다.
수정 사항은 다음과 같습니다. 해당과 같이 바꾸니 마법같이 잘 작동합니다. 그러나 페이지 테이블 kill하는 supplemental_page_table_kill 함수에 문제가 생겨 고치고 있습니다.
기존의 해당 코드를
if (type == VM_UNINIT)
다음과 같이 수정
if (src_page->operations->type == VM_UNINIT)
페이지 삭제 부분을 수정중인데, 문제가 계속 생깁니다. fork-read가 되는 코드는 destroy가 안된다.
→ 일단 계속해서 supplemental_page_table_kill , page_destroy 부분을 수정하고 있다. 해당 부분이 해결되면 다음 것도 해야되는데, 이러다가 mmap를 언제할지…. 계속 디버깅을 해봐야될 것 같다.
내일은 스택 그로우 이해도 해야한다…
채호형이 사준 노티드 도넛을 먹었다. 정말 맛있었다~
