Can someone please explain to me what does fork() != 0 mean? From what I understand I think it means if fork is not false? Or if fork is true then.... I don't understand how Fork() can be true or false, seeing that it just creates a copy of a process into a parent and child. Also if a program where to say if (Fork() == 0) what would that mean?
#include "csapp.h"
int main(void)
{
int x = 3;
if (Fork() != 0)
printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);
}
fork() returns -1 if it fails, and if it succeeds, it returns the forked child's pid in the parent, and 0 in the child. So if (fork() != 0) tests whether it's the parent process.
From man fork
Return Value
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
Assuming success, fork returns twice: once in the parent, and once in the child.
OK, I did the OP a disservice: I don't know where csapp.h comes from, but if it's this one then it isn't doing you any favours. I guess it is a thin wrapper on POSIX (eg. around fork()), but maybe works on other platforms too?
Because you mentioned fork() before Fork(), I assumed the latter was a typo, whereas it's actually a library function.
If you had been using fork() directly, it would be reasonable to expect you to check the manpage.
Since you're using a Fork() function provided by some library, that library really ought to document it, and doesn't seem to.
Standard (non csapp) usage is:
pid_t child = fork();
if (child == -1) {
printf("fork failed - %d - %s\n", errno, strerror(errno));
exit(-1);
}
if (child) {
printf("I have a child with pid %d, so I must be the parent!\n", child);
} else {
printf("I don't have a child ... so I must be the child!\n")
}
exit(0);
Let's try explaining it differently... When the function starts there's 1 process, this process has a int x = 3
Once you hit this line of code:
if (fork() != 0)
Now, assuming the fork() worked, we have two processes. They both have the same execution space, they both are going to run the same code (to a point), but the child will get its own copy of x to play with.
fork() will return a 0 to the child process, so from the child processes' prospective, the rest of the function is this:
printf(("x=%d\n", --x);
exit(0);
The parent process on the other hand, will get a valid value back from the fork() command, thus it will execute:
printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);
What the output at this point will be is anyone's guess... You can't tell if parent or child will run first
But if we assume the parent hits the ++x is the next operation then the output is:
x=4
x=3
x=2
As both parent and child will hit the --x. (the parent's x was 4 after the ++x, will be 3 at the end. The child's x was 3, will be 2 at the end)
From fork() manual:
Upon successful completion, fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent
process. Otherwise, a value of -1 is returned to the parent process, no child process is created, and the global variable errno is set to indi-
cate the error.
After the code execution you have two execution threads. Into the if statement you have the parent process' thread and in else statement you have the child process' thread.
if ( fork() ) {
printf("I am the parent!\n");
} else {
printf("I am the child\n");
}
EDIT
For clarification purpose: fork starts a process, which has a thread, memory and may have other resources. I tried (it seems like that without success) to emphasize the flows of execution by adding the "thread" word.
However, by no means, one can say that "parent" relates to "thread" in "parent process' thread".
Of course, my answer could be improved but I think there are already enough good answers here.
Fork returns 0 for the child process and the process id of the child to the parent process. Hence commonly code has if(fork){ }else code. Which implies that the code inside the if is going to be executed only in a parent.
The better way to deal with it is
pid = fork()
if(pid){
// I am parent. Let us do something that only the parent has to do
}else{
// I am child. Let us do something only the child has to do
}
// This code is common to both
The child pid may be useful to wait upon later or to detach from the parent.
I recommend replacing the if with a switch because there are 3 possible results:
#include <sys/types.h>
#include <unistd.h>
pid_t pid;
switch ((pid = fork ())) {
case -1: /* error creating child. */
break;
case 0: /* I am the child process. */
break;
default: /* I am the parent process. */
break;
}
Related
[SOLVED]
So for this practice exercise I was assigned we are practicing process control. I'm simply wondering why it seems that my child process will never execute (when child_pid == 0). Any help on this issue would be greatly appreciated!
Also, safe_fork() is a function our instructor wrote in order to avoid students opening too many processes.
#include "safe-fork.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void) {
pid_t child_pid;
int pipefd[2];
int pipe_result;
int count;
pipe_result = pipe(pipefd);
if (pipe_result == -1) {
perror("pipe failure");
exit(1);
}
child_pid = safe_fork();
/*Parent Process*/
if (child_pid > 0) {
dup2(pipefd[0], STDIN_FILENO);
scanf("%d", &count);
if (count > 200) {
printf("Long enough!\n");
exit(0);
}
else {
printf("Too short!\n");
exit(1);
}
}
/* Child Process */
else {
dup2(pipefd[1], STDOUT_FILENO);
execl("/usr/bin/wc", "-w");
}
return 0;
}
Here is a suggestion, check for child_pid == 0 explicitly cause it could also be the case that your safe_fork() function failed, also check for those errors i.e child_pid < 0.
Add debug printf statements to check control flow if you already haven't and finally check if the execl call failed.
Also please have a look at this tutorial for creating pipes in C and using them to communicate between a parent and a child process. As I feel there are some issues with how you are handling those file descriptors. A possible reason that you can't see any output is that wc might still waiting for some input.
And another thing you might need to wait for the child process to complete/do something useful or actually be run before checking for its output. Check the other issues first before you worry about this.
Hope this Helps :)
Yes, But no. First you should carefully understand the meaning of fork().
fork(): creates a child process and it returns into TWO PROCESSES, with different return value in each. In parent, it always returns the number that OS has assigned for the newly created child's process id. At the same it returns in newly created child also, as child process will start executing the code copied from parent just after the fork() statement. In child fork always returns zero. So normally after a fork() system call, people check for returned value by fork to differentiate child process and parent process.
particularly in this case after a fork(), there will be two processes with same code and same program states(except both will have different value assigned in child_pid variable). In parent its a non zero value (which is corresponding to child's pid) and in child, its the value zero as the fork returns zero in child.
Now both processes will execute
if (child_pid > 0)
which is true only for parent so parent process will flow into 'if block' and is false for child so it will directly jump to else part and will execute the else block.
What if child_process id is zero?
OS will always assign a non zero value for a child so that fork() will work. And if you have somehow got child process id as zero then parent will fail to enter in 'if block' and will execute else block which is the same as child.
This question already has answers here:
How is it possible for fork() to return two values?
(5 answers)
Closed 7 years ago.
I've decided to learn C, and here is the snippet from one of the books that I use:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t result = fork();
if (result == -1){
fprintf(stderr, "Error\n");
return 1;
}
if (result == 0)
printf("I'm a child with PID = %d\n", getpid());
else
printf("I'm a parent with PID = %d\n", getpid());
return 0;
}
Its output is:
I'm a parent with PID = 5228
I'm a child with PID = 5229
Everything's clear, but how could it be that result == 0 and result != 0 at the same time? It looks like this variable stores two values, because the printf instruction is executed twice. I know, that fork() returns 0 and a parent's PID, but how does result check if it returns true for different conditions?
Because it's not the same variable. When you fork a process, you end up with two totally different processes (see this answer for more detail).
Hence the result variable in the parent is not the same as the one in the child. What you're seeing is two processes, both attached to the same output device, each writing their own message.
In fact, the fork documentation specifically covers that:
On success, the PID of the child process is returned in the parent, and 0 is returned in the child.
So you can use the return value from fork (as you do) to see if you're the parent or child (and to see if it worked as well, it'll return -1 if it fails and you'll be the parent with no child).
The idea is that the parent gets the process ID of the child so it can do something with it (like wait() for it to finish) and the child gets zero. The child can always get the process ID of the parent by calling getppid().
A variable can only hold a single value at a time. What you're seeing is happening because fork() is creating another process: there's now two instances of your program running; one in which result == 0 (the spawned process), and another where result != 0 (the original process)
fork replicates a child from a parent. So the newly created child inherits several properties like shared memory, message queue, file streams etc from the parent. So when you call fork, another process with another variable result is created.
The fork() function create a new process, after this line your program split to 2 from that spot. Because you need to know which process are you, the function return 0 if you are the child process, and some pid if you are the father process.
from the man page:
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
fork() function will create a new process. in parent process, fork() will return the pid of child process, so "result" variable will not equal with 0, and in child process, fork() just return 0, so "result" is 0.
I have this question in my text book that I am not able to wrap my head around. The question is: What is the maximum number of processes running simultaneously in the program code below?
In the code below no return value checks are made to fork(), hence both parent and child will execute all of the code, right? Am I wrong in assuming that in the first fork() call the parent will just wait first and then exit? So the maximum number of processes running at once would be 2? (Just before the parent exits it did a fork).
int main()
{
if ( fork() )
wait(0);
else
exit(0);
if ( fork() )
wait(0);
else
{
if ( fork() )
wait(0);
else
{
if ( fork() )
wait(0);
else
exit(0);
}
}
return 0;
}
I think the code is very poorly written and it is very unclear what actually happens in the code. I would be very thankful for a useful answer.
Thanks in advance.
In the code below no return value checks are made to fork(), hence both parent and child will execute all of the code, right?
No. If success, fork() will return postive number in parent process, 0 in child process. Those if (fork()) will be true in parent process.
Am I wrong in assuming that in the first fork() call the parent will just wait first and then exit?
No. After wait() returns, that parent will continue in the next if (fork()), the child will exit.
So the maximum number of processes running at once would be 2?
No. The right answer is 4.
From the fork(2) manpage:
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
So those conditions behave like this (assuming the fork succeeds):
if ( fork() )
{
// parent, fork() returned the (nonzero) PID of the child process
}
else
// child, fork() returned 0
}
Currently, I am doing some exercises on operating system based on UNIX. I have used the fork() system call to create a child process and the code snippet is as follows :
if(!fork())
{
printf("I am parent process.\n");
}
else
printf("I am child process.\n");
And this program first executes the child process and then parent process.
But, when I replace if(!fork()) by if(fork()!=0) then the parent block and then child block executes.Here my question is - does the result should be the same in both cases or there is some reason behind this? Thanks in advance!!
There is no guaranteed order of execution.
However, if(!fork()) and if(fork()!=0) do give opposite results logically: if fork() returns zero, then !fork() is true whilst fork()!=0 is false.
Also, from the man page for fork():
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
So the correct check is
pid_t pid = fork();
if(pid == -1) {
// ERROR in PARENT
} else if(pid == 0) {
// CHILD process
} else {
// PARENT process, and the child has ID pid
}
EDIT: As Wyzard says, you should definitely make sure you make use of pid later as well. (Also, fixed the type to be pid_t instead of int.)
You shouldn't really use either of those, because when the child finishes, it'll remain as a zombie until the parent finishes too. You should either capture the child's pid in a variable and use it to retrieve the child's exit status:
pid_t child_pid = fork();
if (child_pid == -1)
{
// Fork failed, check errno
}
else if (child_pid)
{
// Do parent stuff...
int status;
waitpid(child_pid, &status, 0);
}
else
{
// Child stuff
}
or you should use the "double-fork trick" to dissociate the child from the parent, so that the child won't remain as a zombie waiting for the parent to retrieve its exit status.
Also, you can't rely on the child executing before the parent after a fork. You have two processes, running concurrently, with no guarantee about relative order of execution. They may take turns, or they may run simultaneously on different CPU cores.
The order in which the parent and child get to their respective printf() statements is undefined. It is likely that if you were to repeat your tests a large number of times, the results would be similar for both, in that for either version there would be times that the parent prints first and times the parent prints last.
!fork() and fork() == 0 both behave in the same way.
The condition itself cannot be the reason the execution sequence is any different.
The process is replicated, which means that child is now competing with parent for resources, including CPU. It is the OS scheduler that decides which process will get the CPU.
The sequence in which child and parent processes are being execute is determined by the scheduler. It determines when and for how long each process is being executed by the processor. So the sequence of the output may vary for one and the same program code. It is purely coincidental that the change in the source code led to the change of the output sequence.
By the way, your printf's should be just the other way round: if fork() returns 0, it's the child, not the parent process.
See code example at http://en.wikipedia.org/wiki/Fork_%28operating_system%29. The German version of this article (http://de.wikipedia.org/wiki/Fork_%28Unix%29) contains a sample output and a short discusion about operation sequence.
Is the child, after the fork, start the program from the beginning or from the place of is parent?
for example, it this program, is the child start from line 1 or line 3?
int i=1
fork()
i=i*2
fork
i=i*2
fork() creates a new process by duplicating the calling process.
The new process, referred to as the child, is an exact duplicate of
the calling process, referred to as the parent, except for the
following points: […]
from fork(2)
As it is an exact duplicate, it will also have the same instruction pointer and stack. So the child will be right after the call to fork(). Now, you may ask, how do I find out whether the current program is the child or the parent? See the manpage on the return value:
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
So if the result of fork() is equal to 0, you're in the child process, if its greater than 0 you're in the parent and if its below 0 you're in trouble.
Please note that this implies that every code which is independent of the result value of fork(), will be executed in both the child and the parent. So if you're for example creating a pool with 16 processes, you should be doing:
for (int i = 0; i < 16; i++) {
pid_t pid = fork()
if (pid == 0) {
do_some_work();
exit(0);
} else if (pid < 0) {
// fork failed
do_some_error_handling();
}
}
If you miss the exit(0), you'll spawn 2¹⁶-1 processes (been there, just with 100 instead of 16. No fun.)
The fork starts from line 3, the point where the fork occurred.
When fork returns, it returns in both the parent (returning the PID of the child) and the child (returning 0). Execution continues from there in both the parent and the child.
As such, typical use of fork is something like:
if (0 == (child = fork()))
// continue as child.
else
// Continue as parent.
The Child will be created at line 2 i.e., fork() but it will start its execution from the line 3 i.e., i = i*2. What confuses me here is your line 4. What are you trying to do there?