#include "csapp.h"
int main()
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
/*
* .------------------------
* |
* |
* |
* .-----------.------------------------
* |
* |
* | .------------------------
* | |
* | |
* | |
* .-----------.------------------------
* fork fork
* i=0 i=1
*/
In the process pic, it seems the code will print "hello" four times. Why print 'hello' three times in my centos?
Unless there's something weird in your csapp.h
header, you should be getting four lines printed out because after the first iteration of the loop (i == 0
before the increment), the fork()
creates two processes, and on the second iteration (i == 1
before the increment), each of those two processes executes fork()
to create two more processes.
When this code is run on macOS 10.14.6, I get 4 lines saying hello
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
Output:
hello
hello
hello
hello
I'd instrument it far more than the bare minimal code shown in the question, though — like this:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: i = %d, PID = %d, PPID = %d, fork = %d\n",
i, (int)getpid(), (int)getppid(), pid);
fflush(stdout);
}
printf("Hello: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
return(0);
}
Note the copious use of fflush()
to avoid the printf()
anomaly after fork()
.
An example output I got from this was:
P0: PID = 5039, PPID = 916
PF: i = 0, PID = 5039, PPID = 916, fork = 5042
PF: i = 1, PID = 5039, PPID = 916, fork = 5043
Hello: PID = 5039, PPID = 916
PF: i = 0, PID = 5042, PPID = 5039, fork = 0
PF: i = 1, PID = 5043, PPID = 1, fork = 0
Hello: PID = 5043, PPID = 1
PF: i = 1, PID = 5042, PPID = 1, fork = 5044
Hello: PID = 5042, PPID = 1
PF: i = 1, PID = 5044, PPID = 5042, fork = 0
Hello: PID = 5044, PPID = 5042
Note that two of the processes reported PPID = 1
because the parent process (5039) had already exited. It would be feasible/sensible to add a loop to wait for children to die and report their exit statuses.
#include <sys/wait.h>
…
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %d, PPID = %d, child %d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
What do you get on CentOS?
I'm running the program from the command line in a terminal window. If you're running this from an IDE or something, you might be losing the output from the orphaned processes. Adding the wait()
loop would prevent the first process from exiting until all (both) its children had exited, leading to an orderly display of the 4 "Hello" lines. I've reworked the output formatting so it is easier to read the output.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: PID = %5d, PPID = %5d, i = %d, fork = %5d\n",
(int)getpid(), (int)getppid(), i, pid);
fflush(stdout);
}
printf("hello\n");
printf("HO: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %5d, PPID = %5d, child %5d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
printf("EX: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
return(0);
}
Sample output (no orphaned processes):
P0: PID = 5245, PPID = 916
PF: PID = 5245, PPID = 916, i = 0, fork = 5248
PF: PID = 5248, PPID = 5245, i = 0, fork = 0
PF: PID = 5245, PPID = 916, i = 1, fork = 5249
hello
HO: PID = 5245, PPID = 916
PF: PID = 5248, PPID = 5245, i = 1, fork = 5250
PF: PID = 5249, PPID = 5245, i = 1, fork = 0
hello
HO: PID = 5248, PPID = 5245
hello
HO: PID = 5249, PPID = 5245
EX: PID = 5249, PPID = 5245
PF: PID = 5250, PPID = 5248, i = 1, fork = 0
hello
HO: PID = 5250, PPID = 5248
EX: PID = 5250, PPID = 5248
WT: PID = 5245, PPID = 916, child 5249 exited 0x0000
WT: PID = 5248, PPID = 5245, child 5250 exited 0x0000
EX: PID = 5248, PPID = 5245
WT: PID = 5245, PPID = 916, child 5248 exited 0x0000
EX: PID = 5245, PPID = 916