fork( ), exec( ), wait( )์ ๊ฐ์ ๊ฒ๋ค์ Process ์์ฑ๊ณผ ์ ์ด๋ฅผ ์ํ System call์.
- fork, exec๋ ์๋ก์ด Process ์์ฑ๊ณผ ๊ด๋ จ์ด ๋์ด ์๋ค.
- wait๋ Process (Parent)๊ฐ ๋ง๋ ๋ค๋ฅธ Process(child) ๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋ช ๋ น์ด์.
์๋ก์ด Process๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ.
๊ทธ๋ฌ๋, ์ด์ํ ๋ฐฉ์์.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // ์ฃผ๋ชฉ
if (rc < 0) { // (1) fork ์คํจ
exit(1);
}
else if (rc == 0) { // (2) child ์ธ ๊ฒฝ์ฐ (fork ๊ฐ์ด 0)
printf("child (pid : %d)", (int) getpid());
}
else { // (3) parent case
printf("parent of %d (pid : %d)", rc, (int)getpid());
}
}
pid : 29146
parent of 29147 (pid : 29146)
child (pid : 29147)
์ ์ถ๋ ฅํจ (parent์ child์ ์์๋ non-deterministicํจ. ์ฆ, ํ์ ํ ์ ์์. scheduler๊ฐ ๊ฒฐ์ ํ๋ ์ผ์.)
[ํด์]
PID : ํ๋ก์ธ์ค ์๋ณ์. UNIX ์์คํ ์์๋ PID๋ ํ๋ก์ธ์ค์๊ฒ ๋ช ๋ น์ ํ ๋ ์ฌ์ฉํจ.
Fork()๊ฐ ์คํ๋๋ ์๊ฐ. ํ๋ก์ธ์ค๊ฐ ํ๋ ๋ ์๊ธฐ๋๋ฐ, ์ด ๋ ์๊ธด ํ๋ก์ธ์ค(Child)๋ fork๋ฅผ ๋ง๋ ํ๋ก์ธ์ค(Parent)์ (almost) ๋์ผํ ๋ณต์ฌ๋ณธ์ ๊ฐ๊ฒ ๋๋ค. ์ด ๋ OS๋ ์์ ๋๊ฐ์ 2๊ฐ์ ํ๋ก๊ทธ๋จ์ด ๋์ํ๋ค๊ณ ์๊ฐํ๊ณ , fork()๊ฐ return๋ ์ฐจ๋ก๋ผ๊ณ ์๊ฐํ๋ค. ๊ทธ ๋๋ฌธ์ ์๋ก ์์ฑ๋ Process (child)๋ main์์ ์์ํ์ง ์๊ณ , if ๋ฌธ๋ถํฐ ์์ํ๊ฒ ๋๋ค.
๊ทธ๋ฌ๋, ์ฐจ์ด์ ์ด ์์๋ค. ๋ฐ๋ก child์ parent์ fork() ๊ฐ์ด ๋ค๋ฅด๋ค๋ ์ ์ด๋ค. ๋ฐ๋ผ์, ์์ ํ ๋์ผํ ๋ณต์ฌ๋ณธ์ด๋ผ ํ ์ ์๋ค.
Parent์ fork()๊ฐ => child์ pid ๊ฐ
Child์ fork()๊ฐ => 0
Parent์ child์ fork ๊ฐ์ด ๋ค๋ฅด๋ค๋ ์ ์ ๋งค์ฐ ์ ์ฉํ ๋ฐฉ์์ด๋ค.
๊ทธ๋ฌ๋! Scheduler๊ฐ ๋ถ๋ชจ๋ฅผ ๋จผ์ ์ํํ ์ง ์๋์ง ํ์ ํ ์ ์๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋ ์ ์๋ค.
pid : 29146
child (pid : 29147)
parent of 29147 (pid : 29146)
child ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ์์
์์ ์์์ int wc = wait(NULL)๋ง ์ถ๊ฐํจ.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // ์ฃผ๋ชฉ
if (rc < 0) { // (1) fork ์คํจ
exit(1);
}
else if (rc == 0) { // (2) child ์ธ ๊ฒฝ์ฐ (fork ๊ฐ์ด 0)
printf("child (pid : %d)", (int) getpid());
}
else { // (3) parent case
int wc = wait(NULL) // ์ถ๊ฐ๋ ๋ถ๋ถ
printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
}
pid : 29146
child (pid : 29147)
parent of 29147 (wc : 29147 / pid : 29146)
wait๋ฅผ ํตํด์, child์ ์คํ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ค. parent๊ฐ ๋จผ์ ์คํ๋๋๋ผ๋, wait ()๋ child๊ฐ ๋๋๊ธฐ ์ ์๋ returnํ์ง ์์ผ๋ฏ๋ก, ๋ฐ๋์ child๊ฐ ๋จผ์ ์คํ๋จ.
๋จ์ fork๋ ๋์ผํ ํ๋ก์ธ์ค์ ๋ด์ฉ์ ์ฌ๋ฌ ๋ฒ ๋์ํ ๋ ์ฌ์ฉํจ.
child์์๋ parent์ ๋ค๋ฅธ ๋์์ ํ๊ณ ์ถ์ ๋๋ exec๋ฅผ ์ฌ์ฉํ ์ ์์.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // ์ฃผ๋ชฉ
if (rc < 0) { // (1) fork ์คํจ
exit(1);
}
else if (rc == 0) { // (2) child ์ธ ๊ฒฝ์ฐ (fork ๊ฐ์ด 0)
printf("child (pid : %d)", (int) getpid());
char *myargs[3];
myargs[0] = strdup("wc"); // ๋ด๊ฐ ์คํํ ํ์ผ ์ด๋ฆ
myargs[1] = strdup("p3.c"); // ์คํํ ํ์ผ์ ๋๊ฒจ์ค argument
myargs[2] = NULL; // end of array
execvp(myarges[0], myargs); // wc ํ์ผ ์คํ.
printf("this shouldn't print out") // ์คํ๋์ง ์์.
}
else { // (3) parent case
int wc = wait(NULL) // ์ถ๊ฐ๋ ๋ถ๋ถ
printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
}
exec๊ฐ ์คํ๋๋ฉด,
execvp( ์คํ ํ์ผ, ์ ๋ฌ ์ธ์ ) ํจ์๋, code segment ์์ญ์ ์คํ ํ์ผ์ ์ฝ๋๋ฅผ ์ฝ์ด์์ ๋ฎ์ด ์์ด๋ค.
์์ด ์ดํ์๋, heap, stack, ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ด ์ด๊ธฐํ๋๊ณ , OS๋ ๊ทธ๋ฅ ์คํํ๋ค. ์ฆ, ์๋ก์ด Process๋ฅผ ์์ฑํ์ง ์๊ณ , ํ์ฌ ํ๋ก๊ทธ๋จ์ wc๋ผ๋ ํ์ผ์ ์คํํ๋ค. ๊ทธ๋ก์ธํด์, execvp() ์ดํ์ ๋ถ๋ถ์ ์คํ๋์ง ์๋๋ค.