why does this fork() out put produce 8 instead of 5? - c

So I have to find the output of this code which is using the fork() method. I thought the output was 5 "hello" s but instead I got 8. Why is that? This is the code:
#include "csapp.h"
void doit()
{
Fork();
Fork();
printf("hello\n");
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}

Here's what your code is doing:
main->doit()->Fork()->Fork()->printf()->return->printf()->exit()
| |
| ----->printf()->return->printf()->exit()
|
----->Fork()->printf()->return->printf()->exit()
|
----->printf()->return->printf()->exit()
As you can see, you have a total of 8 calls to printf().
It would have been easier for you to see what was going on if you chose to print different strings in your main and doit functions.
Setting breakpoint on each printf() call is another effective strategy for figuring out these kinds of problems.

First you call fork and your one process forks into two. Then you call fork in each resulting process and you have a total of 4. Then the 4 processes print hello, return, and print hello again, for a total of 8 hellos.

You create process #1. Before printing anything, process #1 calls fork() and generates a clone that we will call process #2. Both processes #1 and #2 call fork() again, cloning into processes #3 and #4. Now you have 4 processes and each one of them will print hello twice. How many hello are printed?

Related

printf() and fork() produce less output than expected

I'm learning about forking processes and memory management and I have come across this piece of code:
#include <stdio.h>
#include <libc.h>
int main() {
for (int i = 0; i < 3; ++i) {
printf("*");
fflush(stdout);
fork();
}
return 0;
}
By my calculations it should produce 7 stars: initial process prints a star (1 star), forks, now we have 2 processes, each of them prints a star (1 + 2 = 3), then they fork, so we have 4 processes, each of them prints a star and then dies as the program ends.
Thus, we should get 1 + 2 + 4 = 7 stars.
However, during some runs I get only 6 stars, like in the screenshot below:
Other times when I run the program everything is good and I get 7 stars as expected.
So far I have searched in the Internet and haven't found anything like that. Debugging also didn't help.
So, what can cause this strange behavior and how can I fix it?
When running this code from a terminal you will notice that your missing * on some runs is not missing at all but printed after your program is finished.
For better understanding you might print the PID's instead of stars and an additional line when the process is about to finish:
int main() {
for (int i = 0; i < 3; ++i) {
printf("pid %d\n", getpid());
fflush(stdout);
fork();
}
printf ("pid %d terminates\n", getpid());
return 0;
}
The output on a run with missing print(s) will look something like this, indicating the terminal already returned before all processes have finished:
pid 31241
pid 31241
pid 31241
pid 31242
pid 31241 terminates
pid 31243
pid 31244 terminates
pid 31242
pid 31245
pid 31242 terminates
pid 31246 terminates
pid 31247 terminates
pid 31245 terminates
user#machine:~/bla$ pid 31243 terminates
pid 31248 terminates
To fix this you can let the parent process wait for its child processes before returning - this will cause your initial process to finish last and prevent the terminal from returning when there are still child processes running in the background:
while (wait(NULL) > 0);
printf ("pid %d terminates\n", getpid());
However, during some runs I get only 6 stars, ...
Other times when I run the program everything is good and I get 7 stars as expected.
You don't have control in which order the instances print the stars. One example of write() (called implicitly by fflush()), fork() and the implicit exit() at the end of the program could be:
instance 1: write() -> First star
instance 1: fork() -> New instance #2
instance 1: write() -> Second star
instance 2: write -> Third star
instance 2: fork() -> New instance #3
instance 1: fork() -> New instance #4
instance 1: write() -> Fourth star
instance 2: write() -> Fifth star
instance 2: exit()
instance 1: exit() -> Process #1 has finished
---- Process #1 does no longer exist ---
instance 3: write() -> Sixth star
instance 3: exit()
instance 4: write() -> Seventh star
instance 4: exit()
In the example, the sixth and the seventh star are printed, but AFTER the first process has finished.
However, the output of the program(s) is written to some "pipe" or "virtual terminal" and your text editor or IDE copies that output to the screen.
As soon as the "initial" process (instance #1) has finished, your IDE thinks that your program has finished and stops copying the data to the screen - so the sixth and the seventh star in the example are written by your program but they are not copied to the screen by the IDE.
each of them prints a star and then dies as the program ends.
... first, all 4 instances fork and then the 8 instances end.

Number of print statements Fork() [duplicate]

So I have to find the output of this code which is using the fork() method. I thought the output was 5 "hello" s but instead I got 8. Why is that? This is the code:
#include "csapp.h"
void doit()
{
Fork();
Fork();
printf("hello\n");
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}
Here's what your code is doing:
main->doit()->Fork()->Fork()->printf()->return->printf()->exit()
| |
| ----->printf()->return->printf()->exit()
|
----->Fork()->printf()->return->printf()->exit()
|
----->printf()->return->printf()->exit()
As you can see, you have a total of 8 calls to printf().
It would have been easier for you to see what was going on if you chose to print different strings in your main and doit functions.
Setting breakpoint on each printf() call is another effective strategy for figuring out these kinds of problems.
First you call fork and your one process forks into two. Then you call fork in each resulting process and you have a total of 4. Then the 4 processes print hello, return, and print hello again, for a total of 8 hellos.
You create process #1. Before printing anything, process #1 calls fork() and generates a clone that we will call process #2. Both processes #1 and #2 call fork() again, cloning into processes #3 and #4. Now you have 4 processes and each one of them will print hello twice. How many hello are printed?

How many times are executed the programs invoked by execl?

Can you help me with this?
How many times are executed the programs "exam" and "students" invoked by execl? I think the correct answer is 8 runtimes for program "exam" and 0 for "students", because in the two first forks will be created 3 child processes, after that in loop the first fork() will create more 4 processes, since the three children already created also will run this code, thereafter we have a exec that will replace the current code of the 7 processes created and of the actual program and run it(program "exam") 8 times. My reasoning is correct?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main(){
int i;
pid_t
pid=fork();
pid=fork();
for(i=0;i<5;i++){
pid=fork();
execlp("exam","exam",NULL);
if(pid==0){
break;
}
}
execlp("students", "students","sistcomp",NULL);
return 0;
}
Theoretically, you are right. Let me draw a diagram to explain:
+---1 ...
|
+---+---2 ...
|
----+---+---3 ...
fork()|
+---4+---- execlp("exam","exam",NULL);
fork() |
+---- execlp("exam","exam",NULL);
^
after the first two fork()
you see, after 2 fork(), we get 4 process. Take the No.4 as an example, it enter for loop and fork() again, then we get another child process here, this child process and its father will exec execlp("exam","exam",NULL); as you see this will replace the current code.The same is true for No.1, No.2 and No.3.
So, it will be 8 runtimes for program "exam" and 0 for "students".
But, when you run this code, runtimes for program "exam" may be 7 or 6, it may be caused by Copy-on-write(I am not pretty sure about this)
PS:
It is a good practice to use execlp like this:
if (pid == 0)
execlp("exam","exam",NULL);
or
if (pid != 0)
execlp("exam","exam",NULL);

why does fork program printf execute more time [duplicate]

This question already has answers here:
Output of fork() calls
(3 answers)
Closed 8 years ago.
from the man page of fork i read fork create duplicate of parent process. But not able to understand why below program printf execute 8 times. I read Working of fork() in linux link also.
#include <stdio.h>
int main()
{
fork();
fork();
fork();
printf("process\n");
}
In general for n forks in this manner will execute the next statements (in this case printf) 2^n times.
Here is how:
|
+-fork()----------------------------------+
| |
+-fork()-------------+ +-fork()-------------+
| | | |
+-fork()---+ +-fork()---+ +-fork()---+ +-fork()---+
| | | | | | | |
print() print() print() print() print() print() print() print()
Fork works like a binary tree. So its always 2^x number of processes on every x number of fork calls.
Lets understand with your example.
First fork() call:
When the first fork() is called. The parent process creates a new process. So we have 2
threads.
Second fork() call:
At this point we have two processes(main process and a new created process).These two threads will call second fork individually and create 2 new processes each. so we have 4 threads.
You might have got the idea by now. Every time a fork() is encountered all the processes create their respective child processes(double themselves).

fork() execution in for loop

int main(int argc, char** argv) {
int i = 0;
while (i < 2) {
fork();
system("ps -o pid,ppid,comm,stat");
i++;
}
return (EXIT_SUCCESS);
}
Can anyone tell me how many times ps command is executed with an explanation?
I believe the answer is 6.
in the first iteration, fork() is called, splitting the process in 2, thus calling ps twice.
in the second iteration, fork is called again in each process, so you now have 4 processes running ps.
total calls to ps: 2+4=6.
6 times.
It creates a process tree like this:
A-+
|-B-+
| |-C-+
|-D
A does it twice (i=0)
B does it twice (i=0)
C does it once (i=1)
D does it once (i=1)
Note that my usage of letters is to distinguish them. There's no predictable output ordering since process switching is non-deterministic to the eyes of a programmer.
Initial Process
i == 0
-> Fork 1
system call
i == 1
-> Fork 1.1
system call
system call
system call
i == 1
-> Fork 2
system call
system call
I count 6, 2 each from the initial process and the first fork (4), and one from each process forked when i == 1 from those 2 processes.
Of course that's assuming you fix the missing end brace (and define EXIT_SUCCESS), otherwise none, since it won't compile. :-)

Resources