여태까지 상황
현재 상황은 테케를 돌리면 이렇게 뜨는 상황이다.
디버깅을 해봤다.
지금 나는 exec도 못들어가고 있는 상황.
init.c 의 main 함수를 돌고 나서 child process인 test가 돌아가는 건데 나는 main함수도 못돌고 있다.
근데 죽는 지점이 매번 다르다…?🙃
run_actions 에서 여기서 죽음
이번엔 fsutil_put()에서 죽음🙃
이번엔 lock_release()에서 죽음🙃
디버깅을 해봐도 죽는 지점이 계속 달라서 혼란의 연속이었다.
그러다 구세주 프린트신공 마찬옥님 등장.
그도 고군분투를 하다 갑자기 프린트문이 찍히면 안되는 곳에서 찍혀서 이러는것이 아니냐는 합리적의심 후 쓸모없는 프린트문 모두 제거.
vm.c에서 #include "threads/mmu.h" 추가
pml4관련 함수를 vm_do_claim_page()에서 pml4_set_page() 이렇게 버젓이 사용하고 있는데 라이브러리 선언을 위에 안했어서 함수 사용을 실질적으로 못하고 있었다.
pintos -v -k -T 60 -m 20 --fs-disk=10 -p tests/userprog/args-single:args-single --swap-disk=4 -- -q -f run 'args-single onearg'
했을 때
여기서 return true;를 해주지 않았어서 추가했다.
anon_initializer()에서 true를 반환해주지 않으면 vm_alloc_page_with_initializer()에서 uninit_new에서 false 값이 넘어가기 때문에 초기화가 제대로 이루어지지 않아서 해당 부분에서 문제가 생겼던 것이다.
vm_alloc_page_with_initializer()
함수에서 스위치문 안이 의심스러웠다. 처음엔 switch (VM_TYPE(type))
했다가 다른 사람 코드에 switch (type)
되어 있는걸 보고 바꿨던게 문제가 될 수도 있겠어서 원래코드로 바꿨다.
before :switch (type)
after : switch (VM_TYPE(type))
역시 이 문제가 맞았었다.
그냥 type과 VM_TYPE(type)이 어떻게 값이 찍히는지 프린트문으로 찍어봤다.
근데 같다..?
하지만 맨끝에 7번째에는 다르다. VM_TYPE(type)은 0x1이고 type은 0x9로 찍힌다.
마지막에 그렇게 나오는 이유는 type이 유저스택의 스택에 있는 페이지라서 type이 0x9로 찍힌 것이다. 그 이유는 우리가 setup_stack()에서 스택을 할당할 때 이렇게 하기 때문에 VM_MARKER_0을 넣어주었었기 때문이다.
(VM_MARKER_0 이 1000 ->8임)
VM_TYPE()은 이렇게 define 되어있다.
0x9는 이진수로 나타내면 1001이고, 7은 이진수로 나타내면 0111
이걸 AND 연산하면 0001 이다.
따라서, VM_TYPE()으로 감싸줘야 0x1이 된다.
오늘 꽤 오랜시간 나의 에러 해결에 큰 도움을 주신 마찬옥님께 다시한번 감사의 인사를 올린다.
여기까지 했을 때 일단 fork 전까지 성공했다.
이제 copy kill 해야하고 stack growth 한 다음에 mmap하면 ...된다...하하
/* Copy supplemental page table from src to dst */
// 자식 프로세스 생성할때 spt()
bool supplemental_page_table_copy(struct supplemental_page_table *dst UNUSED,
struct supplemental_page_table *src UNUSED) {
struct hash_iterator i;
hash_first(&i, &src->spt_hashmap);
while (hash_next(&i)) {
struct page *src_page =
hash_entry(hash_cur(&i), struct page, hash_elem);
enum vm_type type = src_page->operations->type;
void *upage = src_page->va;
bool writable = src_page->writable;
// type이 uninit이면
if (type == VM_UNINIT) { // uninit page 생성 & 초기화
vm_initializer *init = src_page->uninit.init;
void *aux = src_page->uninit.aux;
vm_alloc_page_with_initializer(VM_ANON, upage, writable, init, aux);
continue;
}
// type이 uninit이 아니면
if (!vm_alloc_page(type, upage, writable)) // uninit page 생성 & 초기화
return false;
// vm_claim_page으로 요청해서 매핑 & 페이지 타입에 맞게 초기화
if (!vm_claim_page(upage)) return false;
// 매핑된 프레임에 내용 로딩
struct page *dst_page = spt_find_page(dst, upage);
memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
}
return true;
}
void hash_page_destroy(struct hash_elem *e, void *aux) {
struct page *page = hash_entry(e, struct page, hash_elem);
destroy(page);
free(page);
}
/* 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. */
hash_clear(&spt->spt_hashmap,
hash_page_destroy); // 해시 테이블의 모든 요소를 제거
}