
Project 2 유저 프로그램까지 구현하며 100퍼센트 이해했냐고 물어본다면 대답을 못할 것 같다.
그렇기에 구현 중에 느낀 이건 왜 이렇게 쓰였을까? 얘는 용도가 뭘까 생각이 난 부분들을
짧게라도 정리하면 좋을 것 같아서 작성하는 글이다.
process_create_initd에서 file_name을 스레드 이름으로 사용하는 이유/* 이 코드를 넣어줘야 thread_name이 file name이 됩니다 */
char *save_ptr;
strtok_r(file_name, " ", &save_ptr);
이런 부분에서 file_name에 어떤 것이 들어가는거지? 라는 궁금증이 생겼다.
그래서 알아보니...
이 코드는 결국 thread_create()에 전달될 스레드 이름을 순수 파일 이름으로 설정하려는 목적.
이라고 한다.
이렇게만 이야기하면 헷갈릴 수 있으니 왜 필요한지 부터 알아보자
thread_create()의 첫 번째 인자는 스레드 이름임.
이 이름은 thread_name() 등으로 출력될 때 사용. 예를 들어
printf("exit: %s: %d", thread_name(), exit_status); 에서.
근데 process_execute()나 process_create_initd()에 전달되는 file_name은 "echo hello world"처럼 인자까지 포함된 문자열.
그래서 "echo"만 따로 떼서 스레드 이름으로 지정.
스레드 이름을 명확하게 실행 파일 이름으로 지정해 주기 위한 절차. 디버깅 메시지, 로그, thread_name() 호출 시 가독성과 추적성이 올라감.

결국 thread의 이름이 무슨 명령어인지 알려주는 이름이라고 쉽게 생각하면 좋을 것 같다.
fork_sema — 부모와 자식 간의 초기 fork 동기화__do_fork)를 마칠 때까지 부모가 대기하도록 함.process_fork()에서 sema_down(&parent->fork_sema);__do_fork() 끝에서 sema_up(&parent->fork_sema);// 부모 thread
tid = thread_create(...); // 자식 스레드 시작
sema_down(&fork_sema); // 자식 초기화 기다림
// 자식 thread (__do_fork 내부)
... fork 준비 ...
sema_up(&parent->fork_sema); // 부모에게 "준비됨" 신호
wait_sema — 부모가 자식 종료를 기다릴 때 사용 (process_wait)process_wait()에서 sema_down(&child->wait_sema);process_exit()에서 sema_up(&cur->wait_sema);// 부모
exit_status = process_wait(child_tid); // 자식 종료까지 대기
// 자식
process_exit() {
sema_up(&wait_sema); // 부모를 깨움
}
exit_sema — 부모가 자식 리소스를 정리할 시간을 기다림process_exit()에서 sema_down(&exit_sema); → 부모가 수거할 때까지 대기process_wait()에서 sema_up(&child->exit_sema); → 자식 종료 후 정리 완료됨을 알림// 자식
process_exit() {
... 리소스 정리 준비 ...
sema_down(&exit_sema); // 부모가 수거할 때까지 대기
}
// 부모
process_wait(child_tid) {
... 자식 상태 수거 완료 ...
sema_up(&child->exit_sema); // 자식에게 "끝났어" 알림
}
✅ 이 구조는 PintOS가 부모-자식 간 리소스를 깔끔하게 정리하고, race condition 없이 안정적으로 종료 처리를 하게 만든 설계.

palloc_get_multiple() — 페이지 여러 개를 할당할 때 사용여러 페이지가 연속적으로 필요한 경우 (예: FDT, argument stack 등)를 위해 물리 메모리를 여러 개 한꺼번에 할당.
일반적인 malloc()은 PintOS 커널에서는 사용할 수 없고, 페이지 단위 할당이 필요한 구조에서 사용.
process_init() 에서 FDT 할당 시:curr->FDT = palloc_get_multiple(PAL_ZERO, FDT_PAGES);
argument_stack()에서 사용자 인자 저장용 스택 설정 시 사용 가능.
스레드 이름 복사나 ELF 로더 등에서도 일부 페이지 단위로 할당 필요 시 사용.
// FDT 2페이지 할당
#define FDT_PAGES 2
thread->FDT = palloc_get_multiple(PAL_ZERO, FDT_PAGES);
PAL_ZERO 플래그는 할당된 메모리를 0으로 초기화함.
반환값은 페이지의 시작 주소이며, 연속된 페이지 메모리 영역이 확보됨.
palloc_free_multiple() — 연속된 여러 페이지를 해제할 때 사용palloc_get_multiple()로 할당한 연속된 페이지를 해제.
FDT, 복사된 인자 메모리, 기타 여러 페이지를 사용하는 커널 자원을 반납.
process_exit() 에서 FDT 반환 시:palloc_free_multiple(cur->FDT, FDT_PAGES);
pg_ofs(addr) == 0, 즉 페이지 경계에 맞춰진 주소여야 함.
page_cnt 는 할당할 때 사용한 것과 동일하게 지정해야 메모리 누수나 패닉 방지.
✔ 시나리오:
// FDT 반납
palloc_free_multiple(thread->FDT, FDT_PAGES);
palloc_get_page() / palloc_free_page() — 단일 페이지 할당/해제단일 페이지가 필요할 경우 사용, 예: file_name 복사용, 임시 메모리, ELF 로더용 버퍼 등.
palloc_get_multiple()의 page_cnt = 1 인 버전이라고 생각하면 됨.
process_create_initd()에서 file_name 복사할 때:fn_copy = palloc_get_page(PAL_ZERO);
palloc_free_page(fn_copy);
// 실행 파일 이름 복사용 1 페이지 할당
char *fn_copy = palloc_get_page(PAL_ZERO);
// 해제
palloc_free_page(fn_copy);
✅ 이 구조는 PintOS가 커널 영역에서 malloc 없이 페이지 단위의 정적 메모리 관리 방식으로 각 자원(FDT, 파일명 복사 등)을 안전하게 할당/회수하도록 하기 위한 설계.
메모리 누수를 막고, 가상 메모리 확장 전까지는 매우 중요한 메모리 관리 수단임.
메모리 누수를 똑바로 못잡으면 마지막 테스트인 multi-oom 통과가 힘들 수 있음