Pintos 구현하며 자식 프로세스 만들때 필요한 구조체와
라이프 싸이클 정리해보려한다
별 거 아닌 거 같은데 모르면 못하는 내용 같아 확실히 정리해두는게 목표다
(감사인사는 접어두도록)
스레드의 ⌜핵심⌟ 이라
자식과 부모간 동기화 하는 법과 필요한 이유 등 가능한거 다 서술한 계획이다
생각보다 필요하다
자식과 부모는 별도 프로세스라 사실 서로를 알아볼 방법이 없다
최소한 서로에 대한 기록이 있어야하기에
이를 위한 구조체를 만들어주고 인자도 넣어줘야 한다
구현한 방식과 유의점 적어 놓을 거다
ദ്ദിˊᗜˋ)
/* thread.h에 넣든지 process.h에 넣든지 하면 된다 */
/* 자식 상태 */
struct child_status {
tid_t tid;
int exit_code; // 자식 종료 코드
bool exited; // 종료 여부
bool waited; // 부모의 wait() 호출 여부
int ref_cnt; // parent + child = 2 로 시작, 소유 카운트
struct semaphore sema; // parent가 wait()에서 대기, 부모 wait일시 down, 자식 exit시 up
struct list_elem elem; // parent->children 에 매달림, 부모의 children list 용
};
/* struct thread.h의 thread다 */
struct thread {
tid_t tid;
struct list children; // struct child_status 노드들의 리스트
struct child_status *my_status; // 내가 종료시 업데이트할 내 노드
/* ...나머지 필드들 */
};
tid: 부모가 wait으로 자식 찾을 때 키
exit_code: 자식이 종료 시 남기는 값 (sys_exit(status), 비정상 종료 )
exited: 자식이 종료했음을 표시
waited: 부모가 wait했는지 확인해 중복 wait방지
ref_cnt: 수명 관리
생성 시 2로 시작 (부모 + 자식)
자식이 process_exit()에서 --ref_cnt후 0이면 free(cs)
부모가 wait() 처리 끝내고 리스트에서 제거 후 --ref_cnt하고 0이면 free(cs)
sema: 동기화의 핵심 (사실 구조체 인자 전부 핵심이긴 하다 ( • ᴗ - ) ✧ )
wait()에서 sema_down()sema_up()로 깨움elem: 부모의 children리스트 사용을 위해
부모 리스트는 딱히 만들 필요 없다는 것에 유의하자
ദ്ദി(。•̀ ᗜ<)
struct child_status *cs = malloc(...)cs->tid = child_tid;
cs->exit_code = -1; // 기본값 -1 권장
cs->exited = false;
cs->waited = false;
cs->ref_cnt = 2;
sema_init(&cs->sema, 0);
list_push_back(&parent->children, &cs->elem);
thread_current()->my_status = cs;
thread_current()->parent = parent;
thread_current()->ppid = parent->tid; // (옵션)
struct thread *cur = thread_current();
struct child_status *cs = cur->my_status;
cs->exit_code = status; // 또는 커널이 정한 에러 시 -1
cs->exited = true;
sema_up(&cs->sema); // wait() 중인 부모를 깨움
if (--cs->ref_cnt == 0) free(cs);
wait(tid) 구현childred 리스트를 tid로 선형 탐색해 cs(자식 상태)를 찾는다. 없으면 -1
cs->waited가 이미 true면 -1 (중복 wait 막기 이를 위해 구조체에 그거 만들어 놓은 거다)
cs->waited = true;
sema_down(&cs->sema); 자식이 아직이면 여기서 잔다 (⸝⸝ᴗ﹏ᴗ⸝⸝) ᶻ
깨어나면 exit_code를 얻는다
부모의 childred 리스트에서 cs제거
list_remove(&cs->elem);
if (--cs->ref_cnt == 0) free(cs);
return exit_code;
free 해야하는지 체크 및 exit_code 반환세마포어가 잘 해줘서 뭐 더 필요없다 - ̗̀( ˶^ᵕ’˶)b
ref_cnt로 free 한번으로 통제해서 더블프리 같은거 방지
자식은 my_status만, 부모의 childred 리스트는 건들지 않아 OK
자식은 sema_up만 호출, 리스트 삽입/삭제 모두 부모측
동일 리스트 건들 리 없으니 락없어도 bb
동기화와 결과 전달 모두 child_status에서 처리 (자식 쪽)
my_status->exit_code 설정 후 sema_up()children에서 tid로 찾고 sema_down() → exit_code 읽고 정리child_status를 공유하는 법이 뭐길래?
힙으로 독립 객체 생성한다
childred 리스트에 elem으로 소유 1my_status 포인터로 소유 1그렇기에 부모-자식만 공유해 문제 X
자식이 또 자식으로 만들어도 서로 간섭이 안 일어나는 이유가 여기 있다
차피 자식 더 만들어도 새로운 간선을 만드는 거라 말이다 ദ്ദി(。•̀ ,<)~✩‧₊