I have below query regarding fork() process:
say I have a code:
if(fork()||fork())
printf("1");
else if(!fork())
printf("2");
else
printf("3");
out of these, which will be printed 1,2 or 3.
I know fork() returns non-zero for parent process and 0 for child process. So when it hits first statement, first fork() call will return say 1 for parent process and 0 for child process. because theres || operator, second fork() will run only when first operand returns 0. so second fork will be called on child and not on parent. Is my understanding correct? if yes, then 1 will be printed by child. Then will it go to else if and else blocks?
Any help will be appreciated!
The first process will print 1.
The child of the original process will print 1 from returning true on the second half of the ||.
The child of the fork after the || will fail the else-if due to the ! and print 3 while its child will print 2 because !0 is true.
Related
tomorrow is my exam and i have difficulty in understanding fork() diagrams, all what i want is to correct me
fork()&&fork()&&fork()
i used this diagram
but my teacher told me that this is wrong and if u draw me this tomorrow i will give u negative marks, and he me told that this is the right one.
The fork() returns the pid of the child in parent address space, some non-negative value. While in the child address space, a 0 is returned.
The && operand doesn't evaluate the rhs if the lhs is false, which is the case in the child process.
After first fork
Parent
true && fork() && fork()
Child
---> never evaluated
false && fork() && fork()
fork()&&fork()&&fork() is equivalent to this:
if(fork()) {
if(fork()) {
fork();
}
}
From the documentation for fork() you can read that it returns the pid of the child in the parent process, and 0 in the child process. So the second diagram is correct. No child process will invoke fork.
I am trying to understand the Output of this Program. But i don't get it. I read about fork and how it works and i tried to understand it, but when i mix it with the && or || Operators i don't understand why the Output is different.
Some Times i get one word, sometimes 2, 3, 4...
#include<unistd.h>
#include<stdio.h>
int main (int argc, char *argv[]) {
(fork()&&fork()) || fork();
printf("Test\n");
return 0;
}
Any Idea how it works?
Somethings that will help in better understanding this code:
1. Fork return values - When you call fork anywhere in your code, you create a new process, and the new process also runs the same code as the parent. The difference between the parent and child process are known from the return value that fork gives. For the child process, fork return value is equal to 0, and for the parent process, it is non-zero.
2. Short circuit logic evaluation - When executing boolean logic in C, the execution is run in a short circuit way.
For a statement && where and are 2 expressions that need to be evaluated to either true or false, the second expression () is checked for its trueness only if the first expression () is evaluated to true. This is because, if is itself false, then regardless of the value of the , the resulting logical expression becomes false, hence making the evaluation of useless.
For a statement like || , is executed only if is false, for a similar reason like above.
In your code snippet, after the first fork() is executed, the child process skips the second fork (due to short circuit of &&) and goes to the third fork(). Resulting in "Test" printed 2 times.
The original parent then encounters the second fork(), and the new child process proceeds to the third fork() and prints Test 2 times again. The parent skips the third fork(), as for it, both the first and second forks are non-zero (short circuit of ||) and prints "Test" once.
Thus "Test" gets printed a total of 5 times.
P1 (fork-1)
/ \
P2(fork-2) P1 (fork-2)
/ \ / \
P3 P2 P4(fork-3) P1
/ \
P4 P5
Based on fork create successfully or not the output should be varied. If all forks are created successfully then 5 times Test should be emerged in output.
1- one output for main thread.(1)
2- main thread create two fork ( firstpart -> (fork() && fork() || secondpart->fork() ) because the first part evaluate as true and the second part do not execute in main thread. So two output should be seen here.(1+2)
3- every two created fork create a new fork but firstpart do not execute in child but secondpart are executed in each child so two another outputs would be seen in overall 5 outputs should be seen.(1+2+2)
First: Sorry for the Question. I had not done enough research, and i didn't consider each fork as child and as Parent.
What i learned is :
The first fork will run and it will create a child.Now we have 2 Processes, Parent returns a number not equal to 0 and Child return 0.
Because the Parent returned a number not 0 will the fork after && also run, and it will create another child Process. The 1 Child Process returned 0 so it wont run after &&. We now have 3 Processes
The fork after || wont run for the Parent because it returned a not 0 Number, but it will run for the child because it returned 0 so we end up with 5 Processes. Hope i am right
I've seen lots of examples of forking in for loops on here, but not much clarification on how it does what it does. Lets use this simple example from an answer of How to use Fork() to create only 2 child processes? as an example.
for (i = 0; i < n; ++i) {
pid = fork();
if (pid) {
continue;
} else if (pid == 0) {
break;
} else {
printf("fork error\n");
exit(1);
}
}
Most of the examples I've seen follow this general format. But what I don't understand is, how does this prevent child processes from forking as well? From my understanding, every child that gets created has to go through this loop as well. But fork() is called at the very beginning of the for loop, and then the 3 comparisons happen. Could someone explain how, even though the children seem to call fork(), this for loop still ensures only the parent can create children?
The child starts at the line after fork. fork returns 0 for the child. In your example, the child would go into the pid == 0 block and break out of the for loop.
After a fork everything is exactly the same for the child and parent (including the next instruction to execute and variable values). The only difference is the return value from fork (0 for the child, and the child's pid for the parent).
When fork returns, it actually returns twice: once to the parent and once to the child. It returns 0 to the child and it returns the pid of the child to the parent.
The if block then detects which process returned. In the parent process, if (pid) evaluates to true, so it executes continue and jumps to the top of the loop.
In the child process, if (pid) evaluates to false, then if (pid == 0) evaluates to true, so it executes break to jump out of the loop. So the child doesn't do any more forking.
But what I don't understand is, how does this prevent child processes from forking as well?
fork() returns 0 in the child. In your example code, that causes the child to break out of the loop instead of performing another iteration, so the children in fact do not call fork().
After checking my Why does this program print “forked!” 4 times?. it seems straightforward to me why.
how does this prevent child processes from forking as well?
if (pid) {
continue;
}
You see when the child is created, and then executes its code and calls fork() it becomes the parent in that stage, thus pid will be 0.
Try man 2 fork. Fork(2) returns a different value for the parent and the child, the parent gets the pid and the child gets 0.
Why does this program print “forked!” 4 times?
#include <stdio.h>
#include <unistd.h>
int main(void) {
fork() && (fork() || fork());
printf("forked!\n");
return 0;
}
The one comes from main() and the other three from every fork().
Notice that all three forks() are going to be executed. You might want to take a look at the ref:
RETURN VALUE
Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the child process to the parent process. Both processes shall continue to execute from the fork() function. Otherwise, -1 shall be returned to the parent process, no child process shall be created, and errno shall be set to indicate the error.
Note that the process id cannot be zero, as stated here.
So what really happens?
We have:
fork() && (fork() || fork());
So the first fork() will return to the parent its non zero process id, while it will return 0 to the child process. That means that the logic expression's first fork will be evaluated to true in the parent process, while in the child process it will be evaluated to false and, due to Short circuit evaluation, it will not call the remaining two fork()s.
So, now we know that are going to get at least two prints (one from main and one from the 1st fork()).
Now, the 2nd fork() in the parent process is going to be executed, it does and it returns a non-zero value to the parent process and a zero one in the child process.
So now, the parent will not continue execution to the last fork() (due to short circuiting), while the child process will execute the last fork, since the first operand of || is 0.
So that means that we will get two more prints.
As a result, we get four prints in total.
Short circuiting
Here, short circuiting basically means that if the first operand of && is zero, then the other operand(s) is/are not evaluated. On the same logic, if an operand of a || is 1, then the rest of the operands do not need evaluation. This happens because the rest of the operands cannot change the result of the logic expression, so they do not need to be executed, thus we save time.
See example below.
Process
Remember that a parent process creates offspring processes which in turn create other processes and so on. This leads to a hierarchy of processes (or a tree one could say).
Having this in mind, it's worth taking a look at this similar problem, as well as this answer.
Descriptive image
I made also this figure which can help, I guess. I assumed that the pid's fork() returned are 3, 4 and 5 for every call.
Notice that some fork()s have a red X above them, which means that they are not executed because of the short-circuiting evaluation of the logic expression.
The fork()s at the top are not going to be executed, because the first operand of the operator && is 0, thus the whole expression will result in 0, so no essence in executing the rest of the operand(s) of &&.
The fork() at the bottom will not be executed, since it's the second operand of a ||, where its first operand is a non-zero number, thus the result of the expression is already evaluated to true, no matter what the second operand is.
And in the next picture you can see the hierarchy of the processes:
based on the previous figure.
Example of Short Circuiting
#include <stdio.h>
int main(void) {
if(printf("A printf() results in logic true\n"))
;//empty body
if(0 && printf("Short circuiting will not let me execute\n"))
;
else if(0 || printf("I have to be executed\n"))
;
else if(1 || printf("No need for me to get executed\n"))
;
else
printf("The answer wasn't nonsense after all!\n");
return 0;
}
Output:
A printf() results in logic true
I have to be executed
The first fork() returns a non-zero value in the calling process (call it p0) and 0 in the child (call it p1).
In p1 the shortcircuit for && is taken and the process calls printf and terminates. In p0 the process must evaluate the remainder of the expression. Then it calls fork() again, thus creating a new child process (p2).
In p0 fork() returns a non-zero value, and the shortcircuit for || is taken, so the process calls printf and terminates.
In p2, fork() returns 0 so the remainder of the || must be evaluated, which is the last fork(); that leads to the creation of a child for p2 (call it p3).
P2 then executes printf and terminates.
P3 then executes printf and terminates.
4 printfs are then executed.
For all the downvoters, this is from a merged but different question. Blame SO. Thank you.
You can decompose the problem to three lines, the first and last lines both simply double the number of processes.
fork() && fork() || fork();
The operators are short-circuiting, so this is what you get:
fork()
/ \
0/ \>0
|| fork() && fork()
/\ / \
/ \ 0/ \>0
* * || fork() *
/ \
* *
So this is altogether 4 * 5 = 20 processes each printing one line.
Note: If for some reason fork() fails (for example, you have some limit on the number of processes), it returns -1 and then you can get different results.
Executing fork() && (fork() || fork()), what happens
Each fork gives 2 processes with respectively values pid (parent) and 0 (child)
First fork :
parent return value is pid not null => executes the && (fork() || fork())
second fork parent value is pid not null stops executing the || part => print forked
second fork child value = 0 => executes the || fork()
third fork parent prints forked
third fork child prints forked
child return value is 0 stop executing the && part => prints forked
Total : 4 forked
I like all the answers that have already been submitted. Perhaps if you added a few more variables to your printf statement, it would be easier for you to see what is happening.
#include<stdio.h>
#include<unistd.h>
int main(){
long child = fork() && (fork() || fork());
printf("forked! PID=%ld Child=%ld\n", getpid(), child);
return 0;
}
On my machine it produced this output:
forked! PID=3694 Child = 0
forked! PID=3696 Child = 0
forked! PID=3693 Child = 1
forked! PID=3695 Child = 1
This code:
fork();
fork() && fork() || fork();
fork();
gets 20 processes for itself and 20 times Printf will go.
And for
fork() && fork() || fork();
printf will go a total of 5 times.
Why does this program print “forked!” 4 times?
#include <stdio.h>
#include <unistd.h>
int main(void) {
fork() && (fork() || fork());
printf("forked!\n");
return 0;
}
The one comes from main() and the other three from every fork().
Notice that all three forks() are going to be executed. You might want to take a look at the ref:
RETURN VALUE
Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the child process to the parent process. Both processes shall continue to execute from the fork() function. Otherwise, -1 shall be returned to the parent process, no child process shall be created, and errno shall be set to indicate the error.
Note that the process id cannot be zero, as stated here.
So what really happens?
We have:
fork() && (fork() || fork());
So the first fork() will return to the parent its non zero process id, while it will return 0 to the child process. That means that the logic expression's first fork will be evaluated to true in the parent process, while in the child process it will be evaluated to false and, due to Short circuit evaluation, it will not call the remaining two fork()s.
So, now we know that are going to get at least two prints (one from main and one from the 1st fork()).
Now, the 2nd fork() in the parent process is going to be executed, it does and it returns a non-zero value to the parent process and a zero one in the child process.
So now, the parent will not continue execution to the last fork() (due to short circuiting), while the child process will execute the last fork, since the first operand of || is 0.
So that means that we will get two more prints.
As a result, we get four prints in total.
Short circuiting
Here, short circuiting basically means that if the first operand of && is zero, then the other operand(s) is/are not evaluated. On the same logic, if an operand of a || is 1, then the rest of the operands do not need evaluation. This happens because the rest of the operands cannot change the result of the logic expression, so they do not need to be executed, thus we save time.
See example below.
Process
Remember that a parent process creates offspring processes which in turn create other processes and so on. This leads to a hierarchy of processes (or a tree one could say).
Having this in mind, it's worth taking a look at this similar problem, as well as this answer.
Descriptive image
I made also this figure which can help, I guess. I assumed that the pid's fork() returned are 3, 4 and 5 for every call.
Notice that some fork()s have a red X above them, which means that they are not executed because of the short-circuiting evaluation of the logic expression.
The fork()s at the top are not going to be executed, because the first operand of the operator && is 0, thus the whole expression will result in 0, so no essence in executing the rest of the operand(s) of &&.
The fork() at the bottom will not be executed, since it's the second operand of a ||, where its first operand is a non-zero number, thus the result of the expression is already evaluated to true, no matter what the second operand is.
And in the next picture you can see the hierarchy of the processes:
based on the previous figure.
Example of Short Circuiting
#include <stdio.h>
int main(void) {
if(printf("A printf() results in logic true\n"))
;//empty body
if(0 && printf("Short circuiting will not let me execute\n"))
;
else if(0 || printf("I have to be executed\n"))
;
else if(1 || printf("No need for me to get executed\n"))
;
else
printf("The answer wasn't nonsense after all!\n");
return 0;
}
Output:
A printf() results in logic true
I have to be executed
The first fork() returns a non-zero value in the calling process (call it p0) and 0 in the child (call it p1).
In p1 the shortcircuit for && is taken and the process calls printf and terminates. In p0 the process must evaluate the remainder of the expression. Then it calls fork() again, thus creating a new child process (p2).
In p0 fork() returns a non-zero value, and the shortcircuit for || is taken, so the process calls printf and terminates.
In p2, fork() returns 0 so the remainder of the || must be evaluated, which is the last fork(); that leads to the creation of a child for p2 (call it p3).
P2 then executes printf and terminates.
P3 then executes printf and terminates.
4 printfs are then executed.
For all the downvoters, this is from a merged but different question. Blame SO. Thank you.
You can decompose the problem to three lines, the first and last lines both simply double the number of processes.
fork() && fork() || fork();
The operators are short-circuiting, so this is what you get:
fork()
/ \
0/ \>0
|| fork() && fork()
/\ / \
/ \ 0/ \>0
* * || fork() *
/ \
* *
So this is altogether 4 * 5 = 20 processes each printing one line.
Note: If for some reason fork() fails (for example, you have some limit on the number of processes), it returns -1 and then you can get different results.
Executing fork() && (fork() || fork()), what happens
Each fork gives 2 processes with respectively values pid (parent) and 0 (child)
First fork :
parent return value is pid not null => executes the && (fork() || fork())
second fork parent value is pid not null stops executing the || part => print forked
second fork child value = 0 => executes the || fork()
third fork parent prints forked
third fork child prints forked
child return value is 0 stop executing the && part => prints forked
Total : 4 forked
I like all the answers that have already been submitted. Perhaps if you added a few more variables to your printf statement, it would be easier for you to see what is happening.
#include<stdio.h>
#include<unistd.h>
int main(){
long child = fork() && (fork() || fork());
printf("forked! PID=%ld Child=%ld\n", getpid(), child);
return 0;
}
On my machine it produced this output:
forked! PID=3694 Child = 0
forked! PID=3696 Child = 0
forked! PID=3693 Child = 1
forked! PID=3695 Child = 1
This code:
fork();
fork() && fork() || fork();
fork();
gets 20 processes for itself and 20 times Printf will go.
And for
fork() && fork() || fork();
printf will go a total of 5 times.