Pint OS 시스템 콜을 구현하다가
도무지 fork(), exec()의 관계, 그리고 부모 프로세스가 왜 자식 프로세스만을 하염없이 기다려야 하는 지에 관하여 의문이 생겼다.
프로세스가 생성될 때는 부모 프로세스를 복제하여 자식 프로세스를 생성하고,
자식 프로세스에서 다른 프로그램을 수행하려할 떄 비로소 아예 별개의 프로세스로 동작된다.
자식 프로세스에서 다른 프로그램을 수행하려하지 않는다면 그저 같은 일을 하는 프로세스가 될 것이다.
그러면 A 프로그램을 수행하는 부모 프로세스, B 프로그램을 수행하는 자식 프로세스가 별개인데, 왜 A프로그램을 수행하는 부모프로세스는 B프로그램이 완료될 때까지 하염없이 기다려야 할까?
주섬주섬.. 운영체제 책을 펴서 공부해본다..
UNIX 시스템에서는 프로세스를 생성하기 위하여 fork()와 exec() 시스템 콜을 사용한다.
wait()는 프로세스가 자신이 생성한 프로세스가 종료되기를 기다리기 원할 때 사용된다.
아하! 부모 프로세스라고 무조건 자식 프로세스를 기다리지 않아도 되는 거였따.
일단 킵 꼬잉 해보자.
운영체제는 프로세스 생성을 위해 이 시스템 콜을 제공한다.
그런데, 특이한 점은 생성된 프로세스가 호출한 프로세스의 복사본이라는 것이다.
자식 프로세스는 부모 프로세스와 완전히 동일하지는 않다.
주소 공간, 레지스터, PC값을 독립적으로 갖는다. 그리고 또 중요한 차이점은 fork() 시스템 콜의 반환값이 서로 다르다.
fork() 이후에 부모 프로세스는 자식 프로세스의 PID를 반환받고, 자식 프로세스는 0을 반환받는다.
단일 CPU 시스템에서 이 두 프로세스를 실행한다면,
프로세스가 생성되는 시점에는 부모와 지식 프로세스 중 하나가 실행된다. 꼭 자식 프로세스가 생성되면서 실행되리라는 법은 없다.
-> 이는 CPU 스케줄러가 선택한다.
부모 프로세스가 자식 프로세스의 종료를 대기해야 하는 경우가 있을 수 있다.
이를 위해서 wait 시스템 콜이 사용된다.
무조건 자식 프로세스가 먼저 수행되어야 하는 경우에 부모 프로세스는 wait()을 호출하여 자식 프로세스가 종료될 때까지 리턴하지 않는다.
프로세스 생성 관련 API 중에서 중요한 시스템 콜이다.
이 시스템 콜은 자기 자신이 아닌 다른 프로그램을 실행해야 할 때 사용한다.
fork() 시스템 콜은 자신의 복사본을 생성하여 실행한다. 이 때, 분명히 다른 프로그램을 실행하고자 하는 경우가 생긴다.
이 때 바로 exec() 시스템 콜을 사용한다.
이는 인자로 실행 파일의 이름 등이 주어지면, 해당 실행 파일의 코드와 정적 데이터를 읽어들여 현재 실행 중인 프로세스의 코드 세그멘트와 정적 데이터 부분을 덮어쓴다.
힙, 스택 공간은 새로운 프로그램의 실행을 위해 다시 초기화 된다.
운영체제 입장에서는 프로그램을 위해 프로세스가 생성되는 것이 아니라,
이미 실행 중인 프로그램을 다른 프로그램으로 대체하는 것이다.
왜 fork()와 exec()을 분리했을까?
UNIX의 쉘을 구현하기 위해서 분리해야 한다고 한다.
그래야만 쉘이 fork()를 호출하고 exec()를 호출하기 전에 코드를 실행할 수 있다고 한다. 이 때 실행하는 코드에서 프로그램의 환경을 설정하고 다양한 기능을 준비한다.
.
.
책만 보면 궁금증이 다 해결되진 않는다..
도대체 왜 기다려야 하는 상황이 생길까? 어떤 상황일까??
나만의 프라이빗 선생 GPT 호출이다.
Q. 부모 프로세스는 왜 자식 프로세스를 기다릴까?
🧟 → 즉, 부모가 기다리지 않으면 좀비가 생긴다!
bash (부모)
└─ fork() → ls (자식)
└─ exit(0) or exit(1) bash는 wait()으로 ls의 결과를 기다리고, 상태를 출력하거나, 다음 명령을 판단하죠.❓ 그럼 “자동 수거”는 왜 안 되는가?
자동 수거는 비결정적이고 예측 불가한 결과를 낳습니다.
• 자식이 언제 죽었는지,
• 왜 죽었는지,
• 죽으면서 무슨 데이터를 남겼는지
이걸 알 수 없게 되기 때문에, 명시적인 수거 설계가 훨씬 강력하고 예측 가능합니다.
오우 업데이트 되면서 모든 대화 메모리가 공유된다더니, 갑자기 특급 정보를 던져줬따 .. 스포 당한 느낌이다.
🧵 PintOS에서는?
• process_wait(tid_t child_tid)를 통해 자식 프로세스가 종료될 때까지 기다리고,
• 자식이 exit(status)를 호출하면, 부모는 그 status를 받아옵니다.
• 그리고 그 시점에 자식의 PCB 및 리소스를 clean-up 해줍니다.
오케이 대충만 이해하고 구현해보도록 하자.