공룡책 ch03. Process -2-
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("Hello, Process!\n");
return 0;
}
Hello, Process!
Hello, Process!
자식 프로세스가 부모 프로세스의 주소 공간을 복사해오고 fork() 이후의 코드를 두 프로세스 다 실행하므로 Hello, Process가 두 번 출력됨
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("Hello, Process! %d\n", pid);
return 0;
}
Hello, Process! 3756
Hello, Process! 0
fork()에서 리턴 받음 pid를 출력하는데 부모는 os로부터 받은 자식의 pid를 출력하고 자식은 0을 출력함
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
int main()
{
pid_t pid;
pid = fork();
if (pid > 0){
wait(NULL);
}
printf("Hello, Process! %d\n", pid);
return 0;
}
Hello, Process! 0
Hello, Process! 10440
조건문을 통해 pid가 0이 아닐 부모 프로세스에 wait()를 걸음.
위에서 fork()만 하던 코드들과는 다르게 자식 프로세스가 종료된 후 부모 프로세스가 작업을 재개하므로 출력 결과를 보면 pid가 0인 자식이 먼저 printf했음을 알 수 있음.
Using the program shown in Figure 3.30, explain what the output will
be at LINE A
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
int value = 5;
int main()
{
pid_t pid;
pid = fork();
if (pid == 0) {
value += 15;
return 0;
}
else if (pid > 0) {
wait(NULL);
printf("Parent: value = %d\n", value);
}
}
Parent: value = 5
부모가 wait에 들어가고 자식이 먼저 15를 더해준 후 종료되고 부모가 출력을 수행하므로 20이라고 착각할 수 있음.
그러나 자식 프로세스가 주소 공간을 복사할 때 전역 변수 value 역시 복사되므로 자식의 value값만 변경되고 부모의 value는 변경되지 않는다.
Including the initial parent process, how many processes are created by
the program shown in Figure 3.31?
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
int main()
{
fork();
fork();
fork();
return 0;
}
위의 코드를 실행했을 때 프로세스가 총 몇 개 생성되는지에 대한 문제이다.
부모는 총 3개의 자식을 생성한다.
첫 번째 fork로 생성된 자식은 2개
두 번째 fork로 생성된 자식은 1개
세 번째 fork로 생성된 자식은 남은 fork가 없으므로 0개
첫 번째 fork로 생성된 자식의 첫 fork로 생성된 자식은 1개의 자식을 생성할 수 있다.
첫 번째 fork로 생성된 자식의 두 번째 fork로 생성된 자식은 0개
두 번째 fork로 생성된 자식의 자식은 0개
다 더해주면 3 + 2 + 1 + 1 = 7
총 자식은 7개가 생성된다.
부모까지 총 8개의 프로세스가 생성된다.
Including the initial parent process, how many processes are created by
the program shown in Figure 3.32?
#include <stdio.h>
#include <unistd.h>
int main()
{
int i;
pid_t pid;
for (i = 0; i < 4; i++) {
pid = fork();
}
return 0;
}
위 문제와 같은 원리로 접근하면 총 16개가 만들어진다.
자식 프로세스에서는 반복문이 처음부터 다시 시작되는 거 아닐까라고 생각할 수 있지만 지역 변수 i까지 같이 복사되므로 반복 횟수가 남아 있다.
Explain the circumstances under which the line of code marked
printf("LINE J") in Figure 3.33 will be reached.
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
int main()
{
pid_t pid;
pid = fork();
if (pid == 0) {
execlp("/bin/ls", "ls", NULL);
printf("LINE J\n");
}
else if (pid > 0) {
wait(NULL);
printf("Child Complete\n");
}
return 0;
}
3.27_process_creation1.c 3.29_process_creation3.c 3.31_process_creation5.c 3.33_process_creation7.c fig3_8_system_call_fork.c
3.28_process_creation2.c 3.30_process_creation4.c 3.32_process_creation6.c a.out
Child Complete
execlp는 fork로 프로세스의 주소 공간에 외부 프로그램을 덮어 씌움.
이 경우 pid == 0인 자식 프로세스에 execlp 코드가 실행되므로 ls가 덮어씌워져 printf("LINE J\n"); 코드는 실행되지 않고 ls가 실행된다.
Using the program in Figure 3.34, identify the values of pid at lines A, B,
C, and D. (Assume that the actual pids of the parent and child are 2600
and 2603, respectively.)
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
int main()
{
pid_t pid, pid1;
pid = fork();
if (pid == 0) { // child process
pid1 = getpid();
printf("child: pid = %d\n", pid); //A
printf("child: pid1 = %d\n", pid1); //B
}
else if (pid > 0) { // parent process
pid1 = getpid();
printf("child: pid = %d\n", pid); //C
printf("child: pid1 = %d\n", pid1); //D
}
return 0;
}
getpid()는 현재 실행 중인 프로세스의 pid를 얻는다.
부모 프로세스의 pid를 2600, 자식은 2603이라고 할 때
A는 0 자식이 fork로부터 반환받은 0
B는 2603 getpid()로부터 반환 받은 자식 프로세스 자신의 pid
C는 2603 fork로부터 반환받은 자식 프로세스의 pid
D는 2600 getpid()로부터 반환 받은 부모 프로세스 자신의 pid이다.
Using the program shown in Figure 3.35, explain what the output will
be at lines X and Y
#include <wait.h>
#include <stdio.h>
#include <unistd.h>
#define SIZE 5
int nums[SIZE] = {0,1,2,3,4};
int main()
{
int i;
pid_t pid;
pid = fork();
if (pid == 0) {
for (i = 0; i < SIZE; i++) {
nums[i] *= i;
printf("CHILD: %d \n",nums[i]); /* LINE X */
}
}
else if (pid > 0) {
wait(NULL);
for (i = 0; i < SIZE; i++) {
printf("PARENT: %d \n",nums[i]); /* LINE Y */
}
}
return 0;
}
사실상 자식 프로세스는 i의 제곱 수, 부모는 i를 그대로 반환하게 된다.