[목표]
fork를 제외하고 모든 테스트 케이스가 돌아가는지 확인해봅니다.
fork도 돌아갈 수 있는 코드를 만듭니다.
일단 벨로그 정리먼저하고 코드보기.
어제의 내용을 벨로그에 게제했습니다.
어제에 이어서 디버깅 중입니다. 왜 이렇게 안되는지 모르겠습니다.
식사를 하고 왔습니다.

코드 디버깅하다가 졸려서 자다 왔습니다.
잠을 잤습니다.
정글 스테이지에서 운영진 티타임을 가졌습니다. 밑에 내용은 대강 이해한대로 적었습니다. 정리가 완료되는대로 따로 포스팅할 계획은 있습니다.
임베디드, 펌웨어 및 하드웨어 제어 개발에 대한 주제로 진행했습니다.
우리가 생각하는 데스크탑과는 다르다. MCU, SoC라는 부품을 가지고 만들어진다.
칩벤더라는 SoC나 MCU를 만드는 회사가 있다. 예를 들어 퀄컴.
제품을 만드는 사람들은 칩을 받아서 우리의 목적에 맞게 고쳐서 사용하여야한다. 회로도가 어떻게 되는지, sdk 등의 자료들을 받는다. 어떤 아키텍쳐가 필요할때, 이러한 ARM64 등의 아키텍쳐가 냉장고나 장비에 들어가게된다.
우리의 제품을 만들기 위해 하드웨어 개발자와 임베디드 소프트웨어의 합작으로 만들어진다.
칩벤더가 문서와 소스코드, 사람을 파견시켜줘서 mcu, soc를 설계하는데 도움을 준다.
해외에서 이러한 mcu, soc 칩을 사와서 커스텀하여 사용한다.
임베디드에서는 OS를 사용할 수도 있는데 임베디드 리눅스, RT 리눅스(시스템 스케줄링만), OS가 없을 수도 있다. 정보가 별로 없어서 GPT를 사용할 수 없다. 임베디드의 정보는 스택 오버플로우나 GPT를 쓴적이 없다. 왜냐하면 정보가 없기 때문이다. 그래서 아까 말한 설계를 도와주는 사람들이나 공식 문서만을 보고 트라이를 해본다.
영상, 소리, 화상, 메카니컬, 소프트웨어 엔지니어등 임베디드쪽은 모두 다양한 사람들과 협업을 많이 한다.
같이 이야기를 많이 해야한다. 컨트롤러에 들어가는 소프트웨어는 펌웨어 개발자라고도 한다.
이러한 펌웨어를 넣는 과정이 어렵다. 롬에다가 직접 구워서 넣어야하기 때문이다.
일반적인 소프트웨어 회사와 좀 다르다.
하드웨어적 관점
칩들에 레지스터들의 목록이 있다. 이걸 어떻게 하냐에 따라 각각 장비들의 처리가 달라진다.
시리얼 통신이나 병렬 통신을 잘 섞어서 잘 작동하게끔 설계하여야한다.
임베디드 OTA → 아마 차량 업데이트 말하는것 같다.
임베디드를 가기위해선 뭐가 중요한가?
→ 어셈블리어와 C언어를 잘아는게 좋다. C언어를 잘하면 좋음.
역시 pintos를 잘하면 os를 이해했다면 임베디드계에서 쉬울 것.
하드웨어지식은 쌓기 쉽지 않을 것이다. 눈으로 봐야 알 수 있기 때문이다.
코딩 컴벤션을 굉장히 중요시 여긴다. 약속을 어기면 싫어함. 젠킨스를 통해 돌려서 잘못된 사람이 있으면 불러서 알아본다고 한다. 코드 리뷰도 많이 한다고 한다. 소스의 품질을 우선시 한다.
알럼나이분 중에서 임베디드에서 일하시는분 말씀으로는 통신이나 네트워크가 중요하다 했는데 중요하게 생각하시는가?
→ 펌웨어도 요즘에는 와이파이로 업로딩하고 올린다. 그래서 중요할 것 같다.
추가적으로 RTOS와 bare-metal 구조 이해가 필요하다.
차량 임베디드쪽으로 가기위해서 어떤 경험을 해야하는가?
→ 그시대의 히트 상품을 찾는게 중요하다. 임베디드 인기 시장이 스마트폰 → 차량 으로 바뀐것 처럼.
원하고자 하는바보단 다른걸 하다가 연차가 쌓이면 다른 쪽으로 전향하면 좋다. 어떤 기술가지고 했느냐가 중요하다.
문화에 대해서
스타트업 규모의 회사: 제조업 기반의 회사가 수직적인 문화가 남아 있을 수도 있다.
자주 이직하는걸 좋아하지 않는다. 웹 & 앱과 다르다.
회사에 갔으면 진득하게 있는걸 좋아한다. 좀 힘들더라도 참고 계속하는게 좋다.
처음 진입장벽은 높을 수 있으나 계속하다보면 빛을 낼 수 있다.
최대한 검증을해서 문제가 없게끔 한다. GNU 라이브러리를 많이 사용한다.(검증을 많이한 라이브러리다)
삼성에서도 GNU 라이브러리를 쓴다. 안정적인 제품을 만드는데에 목적이 있다.
본인이 만든 제품에 대한 프라이드가 있다.
면접이나 임베디드 준비 팁?
범용 칩(통신칩) 들의 스펙들이나 기능들을 공부해서 면접 때 써먹으면 좋을 것이다.
추가로 유윤선 코치님과 말씀을 나누었다.
그냥 여러가지 방법을 찾아봤는데 userprog 단에서 문제가 있는것 같다…
운동 갔다와서 재확인해보겠다.
운동(하체)를 하고 샤워하고 왔다. 이게 샤워를 하니 좀 늦는 것 같아서 내일은 하지말던지 일찍 운동을 하던지 해야겠다.
식사를 하고 휴식을 가졌다.

확인결과 확실히 userprog부터 문제가 있는 것 같다. 그래서 userprog는 권호형 코드로 모두 바꾸고, vm단에서 잘못된것을 색출하고 있다.
vm.c에서는 vm_alloc_page_with_initializer 이 문제 였다. 이유는 정확히 모르겠는데 구현차이인것 같다 그리고,
// 해당 페이지를 spt에 삽입합니다.
page->writable = writable;
이걸 안써서 이상하게 나왔다.
또한 주 핵심 중 하나인데, vm_try_handle_fault를 구현해서 안됐다.
/* 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 = NULL;
//void *va = pg_round_down(addr);
/* TODO: Validate the fault */
/* TODO: Your code goes here */
/* valid address인지 확인 */
page = spt_find_page(spt, addr);
if(page == NULL) {
return false;
}
enum vm_type type = page->operations->type;
if(VM_TYPE(type) != VM_UNINIT) return false;
return vm_do_claim_page (page);
}
spt_find도 수정했다.
struct page *
spt_find_page (struct supplemental_page_table *spt UNUSED, void *va UNUSED) {
struct page *page = NULL;
struct page dummy;
dummy.va = pg_round_down(va);
/* TODO: Fill this function. */
// 기능을 구현하세요.
struct hash_elem *e = hash_find(&spt -> spt_hash, &dummy.hash_elem);
if (e == NULL) return NULL;
//return hash_entry(e, struct page, hash_elem);
// return page;
if(e != NULL)
page = hash_entry(e, struct page, hash_elem);
return page;
vm_get_frame도 수정했다.
static struct frame *
vm_get_frame (void) {
struct frame *frame = NULL;
/* swap 을 구현하기 전에는 할당 실패시 PANIC */
frame = calloc(1, sizeof(struct frame));
if(frame == NULL) PANIC("todo");
void *p = palloc_get_page(PAL_USER);
if(p == NULL) PANIC("todo");
frame->kva = p;
ASSERT (frame != NULL);
ASSERT (frame->page == NULL);
return frame;
}
위의 내용외의 vm.c는 문제가 되지않았다. vm.h의 내용은 vm.c 수정 중 필요없어진 구조체만 삭제했다.
그리고 vm_alloc_page_with_initializer 의 내용이 전체적으로 변경되면서, vm 폴더의 file.c와 file.h, anon.c와 anon.h에 추가되었던
vm/file.c
// 위의 구조체를 외부 접근용 getter 함수 제공 (static 조건 해결)
const struct page_operations *get_file_ops(void) {
return &file_ops;
}
vm/file.h
// extern const struct page_operations file_ops;
const struct page_operations *get_file_ops(void); // 정적 구조체 변경 불가로 추가 선언
vm/anon.c
// 위의 구조체를 외부 접근용 getter 함수 제공 (static 조건 해결)
const struct page_operations *get_anon_ops(void) {
return &anon_ops;
}
vm/anon.h
// extern const struct page_operations anon_ops;
const struct page_operations *get_anon_ops(void); // 정적 구조체 변경 불가로 추가 선언
위의 내용들을 삭제했다.
재준이 형네 코어 타임. 긴급하게 수정해야될 것들이 많아서 참여했다. 팀원들에게 다시 알려주어야함.
initializer가
page_initializer: 페이지 틀만 만들어준다.
vm_initializer: 페이지 틀안에 vm 내용을 작성한다.
결과는 다음과 같다.
(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
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
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
pass 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
FAIL 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
FAIL tests/vm/mmap-zero
FAIL tests/vm/mmap-bad-fd2
FAIL tests/vm/mmap-bad-fd3
FAIL 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
59 of 141 tests failed.
재준이형 코드 픽스할점과 서로 한 부분을 공유했다.
그리고 본인의 것을 설명하는 기회를 가졌다.
야식으로 떡볶이를 먹었습니다.

lock하는 코드가 필요하다고 하여 추가했다. vm.c에 추가했다.
void
vm_init (void) {
vm_anon_init ();
vm_file_init ();
#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); // lock 관련
lock_init(&frame_table_lock); // lock 관련
}
static struct frame *
vm_get_frame (void) {
struct frame *frame = NULL;
/* TODO: Fill this function. */
frame = calloc(1, sizeof(struct frame));
if(frame == NULL) PANIC("todo");
void *kva = palloc_get_page(PAL_USER); // 커널이 접근할 수 있는 물리 페이지 주소
if(kva == NULL) PANIC("todo"); // 사용자 풀에서 페이지를 성공적으로 가져왔는가?
frame -> kva = kva;
//frame -> page = NULL;
lock_acquire(&frame_table_lock);
list_push_back(&frame_table, &frame->elem);
lock_release(&frame_table_lock);
ASSERT (frame != NULL);
ASSERT (frame->page == NULL);
return frame;
}
물론 vm.h에 구조도 추가 했다.
static struct list frame_table; // 전역 frame 리스트(vm_get_frame에서 사용)
static struct lock frame_table_lock; // 멀티쓰레드 환경 보호용
/* The representation of "frame" */
struct frame {
void *kva; // 커널의 가상 주소
struct page *page; // 이 프레임에 매핑된 페이지 (처음은 NULL)
struct list_elem elem; // frame table에 넣기 위한 요소
};
추가적으로 권호형 코드가 아닌 내 코드를 살릴수 있는 부분을 찾고 있다. 찾는 대로 수정한 다음, 재준이형 코드로 롤백을 해야겠다.
재준이형 코드로 롤백하고 exception.c에서 sys_exit하는 부분의 위치를 vm 밑으로, 페이지폴트 이후로 바꿨다.
/* Determine cause. */
not_present = (f->error_code & PF_P) == 0;
write = (f->error_code & PF_W) != 0;
user = (f->error_code & PF_U) != 0;
/* 유저 모드에서의 페이지 폴트라면, 즉시 종료 */
if (user)
{
/* sys_exit()는 프로세스를 exit(-1)하고 thread_exit까지 해 줍니다 */
sys_exit(-1);
NOT_REACHED();
}
#ifdef VM
/* For project 3 and later. */
if (vm_try_handle_fault(f, fault_addr, user, write, not_present))
return;
#endif
/* Count page faults. */
page_fault_cnt++;
수정후
/* Determine cause. */
not_present = (f->error_code & PF_P) == 0;
write = (f->error_code & PF_W) != 0;
user = (f->error_code & PF_U) != 0;
#ifdef VM
/* For project 3 and later. */
if (vm_try_handle_fault(f, fault_addr, user, write, not_present))
return;
#endif
/* Count page faults. */
page_fault_cnt++;
/* 유저 모드에서의 페이지 폴트라면, 즉시 종료 */
if (user)
{
/* sys_exit()는 프로세스를 exit(-1)하고 thread_exit까지 해 줍니다 */
sys_exit(-1);
NOT_REACHED();
}
결론적으로 해당 문제가 모든 사건의 발단이다.
내가 여태껏 vm을 하면서 맞았을 수도 있던 것이 해당 문장으로 인해 args가 제대로 찍히지 않은 것이었다…
2일간 디버깅을 하면서 userprog가 문제가 없다는 가정하에 작성했는데, 의미없는 삽질을 한 기분이다… 공허하다.
-> 그 과정을 통해 load함수를 분석하고 어떤식으로 돌아가는지 조금이나마 이해해서 다행인건지…
이 시간들로 인해 앞서갔던 나의 진도가 뒤처졌다. 제시간에 정리도 못해서 이번주에 정리해야될 양이 말도 안되게 늘어났다. 구현은 해서 진도는 빼야하는데 해야될 정리는 많고… 진퇴양난이랄까…
재준이형 코드 롤백하고 process.c의 내코드를 대부분 살릴 수 있었다. 이제 pass가 잘 되니 다행이다.
syscall.c의 check_user_address 부분을 수정했다. 재준이형이 픽스해주었다. 페이지 폴트 나와도 spt_find_page 로 재검사를 실시한다.
/* check_user_address(const void *uaddr){}
널 포인터 차단 : !uaddr → NULL 이면 즉시 프로세스 종료
유저 영역 검사 : !is_user_vaddr(uaddr) → 주소가 PHYS_BASE 이상(커널 영역)에 있으면 종료
매핑 여부 검사 : pml4_get_page(..., uaddr) == NULL => 가상 → 물리 매핑이 안 돼 있으면 종료
*/
void check_user_address(const void *uaddr)
{
#ifndef VM
// project 2
if (!uaddr || !is_user_vaddr(uaddr) || pml4_get_page(thread_current()->pml4, uaddr) == NULL)
{
sys_exit(-1);
}
#else
// project 3
// spt 매핑 여부 검사 : spt_find_page() == NULL -> exit()
if (!uaddr || !is_user_vaddr(uaddr) || spt_find_page(&thread_current()->spt, uaddr) == NULL)
{
sys_exit(-1);
}
#endif
}
최종적으로 재준이형 코드 패치 후 54개 FAIL이 나온다.
(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
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
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
pass 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
54 of 141 tests failed.
드디어… fork를 해결하러 kill 관련 문제를 해결해봅니다.