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
자식이 또 자식으로 만들어도 서로 간섭이 안 일어나는 이유가 여기 있다
차피 자식 더 만들어도 새로운 간선을 만드는 거라 말이다 ദ്ദി(。•̀ ,<)~✩‧₊