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().
Related
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include<sys/wait.h>
int main(){
int num = 2;
if (!fork()){
num++;
printf ("First: num = %d\n", num);
}else{
wait(NULL);
if (!fork()){
num++;
printf ("Second: num = %d\n", num);
}else{
wait(NULL);
num++;
printf ("Third: num = %d\n", num);
fflush(stdout);
exit(0);
}
}
fflush(stdout);
}
Can someone explain why num ends up being 3? I couldn't find a good explanation on fork().
What does (!fork()) even do??
fork is a Unix system call that duplicates a process. The program continues running twice, once in the parent process and once in a new child process. In the child process, fork returns zero, which is how the child can know it is the child. In the parent, it returns a process identification number for the child. (If an error occurs, it returns −1.)
This code:
if (!fork()){
num++;
printf ("First: num = %d\n", num);
says to create a child, then, in the child, increment num and print it. (In the child, fork returns zero, so !fork() is true.)
At this point, num is still 2 in the parent, because it was 2 when the fork was executed, and the num++ in the child incremented the child’s copy of it and did not affect the parent’s num.
In the else code:
wait(NULL);
if (!fork()){
num++;
printf ("Second: num = %d\n", num);
wait(NULL) says to wait for all children to finish execution, then create another child. That child does the same thing as above. Since it had 2 in num when it was created, the incremented produces 3, and the child prints 3.
The third piece of code does the same thing. The fflush calls are unnecessary.
Fork will create a new process based on the process you have created with your code. So when fork has created a new process it will return 0 for success.
And that is the reason for the output 3.
A detaied explanation how fork works can be found here: Fork-doc
I have been learning about fork in c and i have this program:
int main(void) {
int i;
printf("Start program\n");
printf("This is parent process %d: %d\n", getpid(), i);
int pid = fork();
printf("%d ", pid);
if(pid == 0) {
printf("This is process %d: %d\n", getpid(), i);
}
return 0;
}
This is the output:
Start program
This is parent process 4467: 0
4578 Start program
This is parent process 4467: 0
0 This is process 4578: 0
I do not understand why the parent code is called twice.
stdout is buffered. See e.g. setvbuf(3).
You forgot to call fflush(3) before doing your fork(2). As a rule of thumb, you'll better do fflush(NULL) before any fork().
That could explain the observed behavior (because flushing happens later in both parent and child processes, e.g. at program exit or return from main in crt0). You might (on Linux) use strace(1) to understand more exactly what is happenning.
BTW, fork(2) could fail. You should handle that (that is, handle the pid == -1 (or pid<0) case...).
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
I don't really understand how fork() works.I understand examples with one fork,but when there are more than one call I don't.I have an example like this and it prints 4 lines of hello, how many processes are created?
int main(void)
{
fork();
fork();
printf("hello\n");
return 0;
}
After fork() call, both processes (original and spawned) continue to execute from next line of code. So both processes execute second fork() instruction, so in the end you have 4 processes. Hence you see 4 instances of "hello" lines printed.
One picture is worth a thousand words:
The fork() syscall essentially creates a "clone" of the process executing it. Both "clones" run almost identically (except for the return value of fork()).
The first call to fork() is executed by one process (let's call that one "P"), which creates a second process "C". Now there are two processes, which both execute the second line in your main() function. So both processes, P and C, create a new process. This is why you end up with a total of 4 processes, all of which print "hello" exactly once.
The following example might make that behaviour a bit clearer:
int main() {
printf("process %d: start\n", getpid());
int r1 = fork();
printf("process %d: first fork() returned %d\n", getpid(), r1);
int r2 = fork();
printf("process %d: second fork() returned %d\n", getpid(), r2);
}
On my system, it outputs the following:
process 12953: start
process 12953: first fork() returned 12954
process 12954: first fork() returned 0
process 12953: second fork() returned 12955
process 12955: second fork() returned 0
process 12954: second fork() returned 12956
process 12956: second fork() returned 0
System information: I am running 64bit Ubuntu 10.10 on a 2 month old laptop.
Hi everyone, I've got a question about the fork() function in C. From the resources I'm using (Stevens/Rago, YoLinux, and Opengroup) it is my understanding that when you fork a process, both the parent and child continue execution from the next command. Since fork() returns 0 to the child, and the process id of the child to the parent, you can diverge their behavior with two if statements, one if(pid = 0) for the child and if(pid > 0), assuming you forked with pid = fork().
Now, I am having the weirdest thing occur. At the beginning of my main function, I am printing to stdout a couple of command line arguments that have been assigned to variables. This is this first non assignment statement in the entire program, yet, it would seem that sometimes when I call fork later in the program, this print statement is executed.
The goal of my program is to create a "process tree" with each process having two children, down to a depth of 3, thus creating 14 total children of the initial executable. Each process prints its parent's process ID and its process ID before and after the fork.
My code is as follows and is properly commented, command line arguments should be "ofile 3 2 -p" (i haven't gotten to implementing -p/-c flags yet":
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
if(argc != 5)//checks for correct amount of arguments
{
return 0;
}
FILE * ofile;//file to write to
pid_t pid = 1;//holds child process id
int depth = atoi(argv[2]);//depth of the process tree
int arity = atoi(argv[3]);//number of children each process should have
printf("%d%d", depth, arity);
ofile = fopen(argv[1], "w+");//opens specified file for writing
int a = 0;//counter for arity
int d = 0;//counter for depth
while(a < arity && d < depth)//makes sure depth and arity are within limits, if the children reach too high(low?) of a depth, loop fails to execute
//and if the process has forked arity times, then the loop fails to execute
{
fprintf(ofile, "before fork: parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent and self id to buffer
pid = fork(); //forks program
if(pid == 0)//executes for child
{
fprintf(ofile, "after fork (child):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
a=-1;//resets arity to 0 (after current iteration of loop is finished), so new process makes correct number of children
d++;//increases depth counter for child and all of its children
}
if(pid > 0)//executes for parent process
{
waitpid(pid, NULL, 0);//waits on child to execute to print status
fprintf(ofile, "after fork (parent):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
}
a++;//increments arity counter
}
fclose(ofile);
}
When I run "gcc main.c -o ptree" then "ptree ofile 3 2 -p", the console is spammed with "32" a few times, and the file "ofile" is of seemingly proper format, but a bit too large for what I think my program should be doing, showing 34 child processes, when there should be 2^3+2^2+2^1=14. I think this is somehow related to the statement that is printing "32", as that would seem to possibly spawn more forks than intended.
Any help would be greatly appreciated.
When you call printf, the data is stored in a buffer internally. When you fork, that buffer is inherited by the child. At some point, (when you call printf again, or when you close the file), the buffer is flushed and data is written to the underlying file descriptor. To prevent the data in the buffer from being inherited by the child, you can flush the FILE * before you call fork, via fflush.