So I am continuing some more problems on Fork() and found some sample code on a website called geeksforgeeks. The following code segment:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
void forkexample()
{
int x = 1;
if (fork() == 0)
printf("Child has x = %d\n", ++x);
else
printf("Parent has x = %d\n", --x);
}
int main()
{
forkexample();
return 0;
}
Now I can see why the solution can be either Child has x = 2 and Parent has x = 0 but I am having some issues trying to visualize the tree. The big problem that I have visualizing this is that the first if statement is for the child process, so how would the tree look? Here is what I have come up with in terms of a visualization of this program.
Or would the main node on Level 0 be a Child node because of the order of the if statement coming first (this is a possibility but the else statement could come first as well as it is running concurrently).
Any help? Is this visualization correct or is there something I am missing?
Would appreciate the help , thank you.
No, your visualization is wrong.
After the fork you have TWO processes: Parent and Child. (PERIOD)
A single parent may spawn multiple children, and each may spawn children of their own. But after a single fork, the "tree" is two "nodes".
Not sure if you are trying to graph:
Processes over time, then YES, you are correct, one process has become two.
Process relationship, then NO, you should only have one parent, one child.
Execution path, I guess... at some point fork() is called, next thing you know, you have two processes executing the if() statement.
I don't see where the question is here..
The schema is good it's like this. Fork() creates a new process by duplicating the calling process. 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 (google). You must check the return value to be sure that you're in the child process which is running independently.
Try this :
#include <unistd.h>
int main()
{
pid_t p;
int x;
x = 1;
p = fork();
printf("pid = %d\n", p);
if (p == 0) {
printf("Child has x = %d and pid = %d\n", ++x, p);
sleep(1);
} else {
printf("Parent has x = %d and pid = %d\n", --x, p);
sleep(1);
}
}
They are executed at the same time because they are independant but the parent is primary at the ouput
Nicolas
Related
This isn't in code review because I do not understand the full concept of the code to start with. If it should still be moved just let me know.
I have some code and I would like to explain my thoughts on it, and I am hoping someone can tell me where I am going wrong or getting confused at because I am still not fully sure what is occurring.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid, pid1;
pid = fork();
if (pid < 0) {
fprintf (stderr, “fork() failed\n”);
return(1);
}
else if (pid == 0) {
pid1 = getpid();
printf (“pid = %d\n”, pid); // A
printf (“pid1 = %d\n”, pid1); // B
}
else {
pid1 = getpid();
printf (“pid = %d\n”, pid); // C
printf (“pid1 = %d\n”, pid1); // D
wait (NULL);
}
return 0;
}
From what I understand, we have two process ID's, the parent (pid) and the child (pid1).
Once I call pid = fork(), I believe that the child is initiated and is given the id of 0, while the parent get's the ID of the child, let say 1337. So pid = 1337 and pid1 = 0.
So we skip the first if as no error has occurred (pid < 0), we skip the second if as well since pid does not equal 0, and then we enter the final if where C will print 1337 and D will pint out 0.
This then waits until the child is done, I think.
After that, I assume that the copied process (fork()) will then run the else if (pid == 0) but I am confused on why, because the pid is still 1337..
TLDR: If the third if should be executing first, then how do I get to the second if, but if this logic is all wrong please correct me.
A fork creates makes a (near-perfect) copy of the running process. One difference, as you surmised is the return value of fork() itself. So, assuming the fork works you have two processes executing the same code. One, the child, takes the if (pid == 0) ... path, while the parent takes the else... path. You have no information about the order in which the two processes do their work. Maybe the child goes first, maybe the parent, maybe half way through they take turns, maybe you have two processors and they run together...
Imagine you have this program written on a piece of paper and you are following along with your finger, sliding it down the page. When you get to the fork, take the paper to a copier, make a copy, put both pieces of paper on the table, put a your index finger from each hand on one of the pieces, move both your fingers, each sliding down their own sheet of paper.
Everything you said is not correct
after the fork() call is executed, the child and the parent process runs in parallel, both executing the code of the program that is there after fork(). The only difference would be the pid. The child will run the same program with the pid = 0, and the parent will run the same program with the pid = (pid of child). They seperate out, both having a copy of all the variables of the program, but a different copy of the pid variable.
pid is 0 in the child and the process ID of the child in the parent.
pid1 is set to the process ID of the current process. The value in the child's copy of pid1 is identical to the value of the parent's copy of pid.
I have two code samples here
#include<stdio.h>
int main()
{
int i = 0;
i++;
fork();
printf("i - %d, pid - %d, addr -%p\n",i,getpid(),&i);
return 0;
}
user#Ubuntu ~/Arena/c $ ./a
i - 1, pid - 6765, addr -0x7fffd892950c
i - 1, pid - 6766, addr -0x7fffd892950c
with my second program being
#include<stdio.h>
int main()
{
int i = 0;
i++;
printf("i - %d, pid - %d, addr -%p\n",i,getpid(),&i);
fork();
return 0;
}
user#Ubuntu ~/Arena/c $ ./b
i - 1, pid - 6772, addr -0x7fff39120f2c
Well as far as I know fork should create a COMPLETE copy of the parent program from top to bottom and execute it, if it is that way why is the position of fork() call making such a big difference ? Could some one explain why is the printf omitted in my second program ?
fork() creates a copy of the process, and continues executing both processes at the point you call fork().
So in your second example, your printf is executed before the fork when there is only one process.
Fork creates a complete copy of your program but execution continues from the point in which fork is called. Put printf after the fork and see what happens.
Usually a fork call will be followed by a check if fork returned the pid of the child or not. If it did, then your current running process is the parent which received the child's pid in order to be able to manage the child, if it didn't then your current running process is the child.
For further enlightenment, try:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i = 0;
i++;
printf("A: i - %d, pid - %d, addr -%p", i, getpid(), &i);
fork();
printf("\nB: i - %d, pid - %d, addr -%p\n", i, getpid(), &i);
return 0;
}
The first printf() doesn't include a newline, so the output is held in memory. The second printf() includes newlines, so the output appears after the program has forked. You should see the same information in the two lines tagged A; you should see different information in the two lines tagged B.
In a single-threaded application, the parent and child processes are almost identical except for the PID, Parent PID, and the value returned by fork(). For the full details, see the POSIX specification of fork().
can anybody explain me working of fork in detail
#include<unistd.h>
#include<stdio.h>
int main ()
{
int i, b;
for (i = 0; i < 2; i++) {
fflush (stdout);
b = fork ();
if (b == -1) {
perror ("error forking");
}
else if (b > 0) //parent process
{
wait ();
printf ("\nparent %d", getpid ());
}
else
printf ("\nchild %d %d", getpid (), getppid ());
}
return 0;
}
its just i need to know that if fork have same code as parent then this for loop should never stop creating child processes (every child will have its own for loop)
Yes, each child will continue the loop, but the operative word here is "continue". The variable i will be inherited by the first child, and then increased, and this increased value is inherited by the second child, etc.
The same will happen in the children, as i is inherited and keeps it value from the parent process. This means that the loops will soon end in all children.
When you fork, the child process will continue with the same next instruction as the parent one and the values.
So it will stop one day ;)
Take a look at a similar question : fork in a for loop
Yes although the parent and child code are the same but in parent the fork returns the child process id hence in parents code, the variable b contains the child's pid whereas the in child, the fork returns 0, hence in the child code segment the variable b will have 0 and so does we can achieve different jobs even though forking will have same parent code in child.
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;
}
I have studied that during a fork, the data and code segment of the parent process gets duplicated into the child process.
Kindly see the program below.
int main()
{
int a = 5;
pid_t pid;
pid = fork();
if(pid == 0)
{
printf("In child a = %d",a);
}
else
{
printf("In parent a = %d",a);
}
return 0;
}
Here a is in the stack segment of parent process as it is declared inside the function, main(). The child process should only get copy of the code and data segment of the parent process and not the stack during fork(). But when I run the program, I can see that the child process is able to access the variable 'a' also. Thats means somehow the stack of parent process is also copied into the child process.
Kindly tell me the reason for this and correct me if my understanding is wrong.
You should check the docs again. fork creates an "exact copy of the calling process". Admittedly, there are a lot of exceptions, but the stack is not one of them.
Also, if the stack wasn't duplicated, the very common idiom (also used in your code) of checking the return value (almost always a stack variable) from fork would fail. There wouldn't be a stack position for pid unless the stack (including stack pointer) was duplicated.
That isn't a good test - as Matthew has pointed out, fork() gives you an exact copy of the parent process, including the stack (else the child would be unable to return from this function).
A better test is to modify 'a' in the parent and observe it in the child, like this:
#include <stdio.h>
#include <unistd.h>
int main()
{
int a = 5;
pid_t pid;
pid = fork();
if (pid == 0)
{
sleep(5);
printf("In child a = %d\n",a);
}
else
{
a++;
printf("In parent a = %d\n",a);
}
return 0;
}
and the result is correct:
pandora:~/tmp$ cc -o x x.c
pandora:~/tmp$ ./x
In parent a = 6
pandora:~/tmp$ In child a = 5