I'm trying to trace this program. I see that it outputs 4 times when I run it, but I don't understand why.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
if (fork() == 0)
fork();
else
{
fork();
fork();
printf("%d\n", getpid());
}
}
To my knowledge, the if/else forks my program, then if we're in the child, it forks again. If we're in the parent, it runs the code in the else block. I get confused when I try to trace after this point, though.
Once the else statement forks again, aren't we in another child?
When do the children stop being spawned?
After getting it explained for me, I understand it now.
The first fork will spawn a child (let's call it c1):
if (fork() == 0)
The return value of fork is 0 when you're in the child. So, c1 will execute the if statement block:
fork();
The child created here, c2 (as well as c1) will both die, as they aren't going to execute the else block.
Meanwhile, the parent process will execute the else block.
fork();
This creates another child of the original parent process (c3). c3 will execute the next fork in the else block.
fork();
Now, we'll have c4, too.
Meanwhile, the original parent process will still have a fork that hasn't run. This creates the final child process, c5.
At the end of the run, there will be 4 prints: The original parent process, c3, c4, and c5.
fork in if is executed. There are two processes now child C1 and parent. Parent gets a non-zero number. Child gets 0.
Parent enters else block as it got non-zero return from fork. Now again there are two processes child C2 and parent - after executing fork in else block.
Parents fork again with C3.
Child C2 forks again with C4.
Note that C1 also forked but it will not do anything other than ending the if block. (We don't care about this).
So 4, printf execution - one by Parent, C2, C3 and C4.
The key one line Golden rule is:-
Both parent and child process start their execution right after the system call fork()
And each process ends when the control reaches the end of the function here it is main(). (Answering your last question).
Related
When I run below program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
//multiple children of the same parent
void main(){
int pid,i;
for(i=0;i<3;i++){
pid = fork();
if(pid<0)
printf("fork failed.");
else if(pid>0){
wait(NULL);
printf("i =%d, Child has finished. I am the parent[PID=%d].\n",i,getpid());
_exit(0);
}
else{
printf("i = %d, pid =%d, I am the child[PID=%d], parent[PID=%d] \n",i,pid, getpid(),getppid());
}
}
}
I got the following output:
i = 0, pid =0, I am the child[PID=7720], parent[PID=7719]
i = 1, pid =0, I am the child[PID=7721], parent[PID=7720]
i = 2, pid =0, I am the child[PID=7722], parent[PID=7721]
i =2, Child has finished. I am the parent[PID=7721].
i =1, Child has finished. I am the parent[PID=7720].
i =0, Child has finished. I am the parent[PID=7719].
However, I can’t understand the output.
If we trace the tree. Assuming that the parent represents the bash running this program.
So after fork we will have a child (call it C1) for that parent. The parent has to wait for it’s child because of the Wait(NULL) system call which is going to receive the SIGCHLD signal (PID) number returned by the child to the parent to terminate. Then another fork() has been done producing another child from (C2). However, there is no other child produced by the parent (C3) as in the normal case scenario without the exit(0) in the parent.
In this case n forks = n children (3 forks are going to produce only 3 children not 8).
Can someone help me to understand why the there is no child (C3) for the parent (bash) since it was waiting for C1, so it didn’t exit from the program.
Here's the walkthrough:
Process P creates C1
Process P then blocks waiting for C1 [i=0]
C1 prints the "I am the child" and loops back [i=1]
C1 forks C2
C1 blocks waiting for C2
C2 prints "I am the child" and loops back [i=2]
C2 forks C3
C2 blocks waiting for C3
C3 prints "I am the child" and the loop terminates
C3 exits
C2 unblocks, prints that C3 has exited and then itself exits
C1 unblocks, prints that C2 has exited, and then exits
P unblocks, prints that C1 has exited, then exits
There are not 8 children because the parent never finishes the full loop iteration except in the very last case. Look at it from just process P's perspective: you fork a child, wait for it to finish, and then exit.
Excluding the initial parent process, how many processes will be created by the following piece of code:
fork();
wait(0);
fork();
wait(0);
fork();
I was thinking of 7 processes because the father always waits for the child to end, but the child never exits. So it would be a 2**n - 1.
Every call to a fork function will create a new process. Every process (including the parent) will execute the code following its fork call. Every parent will wait for its child to die (remember that when a child calls fork, it also becomes a parent).
Draw a schema to be sure:
This gives as 7 processes, excluding the parent process.
Read the tree from its rightmost branch, and then maybe the following comments make sense:
fork(); // Process 'c0' was created
wait(0); // Parent process 'p' waits for its child 'c0' to change state.
fork(); // c1, c4
wait(0); // c0, p
fork(); // c2, c3, c5, c6
The Online Demo I created with printing statements and processes' IDs confirms that.
Reminder of the 0 argument in wait():
wait for any child process whose process group ID is equal to that of the calling process.
Read more in C - meaning of wait(NULL) when executing fork() in parallel.
Notice that the number of processes won't change if you comment out the wait calls.
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.
What I am trying to do in my code is have a parent process that forks two children processes. This is how I've done it:
pid = fork();
if(pid != 1)
pid1 = fork();
The next thing I'm trying to do is switch between the processes continuously (from child to other child to parent, in that order) using semaphores. ie the child process will say A, the other child will say B, the parent will say C, the child will say D, and so on.
My two questions are:
Say you call sem_wait(sem) in a semaphore and the process blocks as it should. You then move on and the other process ends up calling sem_post(sem). Will the code following the sem_wait be immediately executed after the sem_post? ie does the execution "jump back" to the code after the sem_wait even if it doesn't come "next" in the program?
if(stuff){
a;
sem_wait(sem);
b;
}
c;
sem_post(sem);
Will b be executed even though it's "before" the post in terms of coming before it textually?
How can I identify the processes so that I may give one of them permission to execute? I have to confirm that a process is either child 1 , child 2 or parent before I give it permission to execute the code, but how can I tell? I tried to check using if statements (if(pid) != 0, if(pid() == 0 and if(pid1 == 0) assuming that the parent would have a return value of 0 for the the first fork and the children would have zero's for their respective forks) but this did not work. I checked their PID's and PPID's and they were all over the place).
All help is appreciated, thank you
Consider the code:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
/* main --- do the work */
int main(int argc, char **argv)
{
pid_t child;
if ((child = fork()) < 0) {
fprintf(stderr, "%s: fork of child failed: %s\n",
argv[0], strerror(errno));
exit(1);
} else if (child == 0) {
// do something in child
}
} else {
// do something in parent
}
}
My question is from where does in the code the child process starts executing, i.e. which line is executed first??
If it executes the whole code, it will also create its own child process and thing will go on happening continuously which does not happen for sure!!!
If it starts after the fork() command, how does it goes in if statement at first??
It starts the execution of the child in the return of the fork function. Not in the start of the code. The fork returns the pid of the child in the parent process, and return 0 in the child process.
When you execute a fork() the thread is duplicated into memory.
So what effectively happens is that you will have two threads that executes the snippet you posted but their fork() return values will be different.
For the child thread fork() will return 0, so the other branch of the if won't be executed, same thing happens for the father thread.
When fork() is called the operating system assigns a new address space to the new thread that is going to spawn, then starts it, they will both share the same code segment but since the return value will be different they'll execute different parts of the code (if correctly split, like in your example)
The child starts by executing the next instruction (not line) after fork. So in your case it is the assignment of the fork's return value to the child variable.
Well, if i understand your question correctly, i can say to you that your code will run as a process already.When you run a code,it is already a process , so that this process goes if statement anyway. After fork(), you will have another process(child process).
In Unix, a process can create another process, that's why that happens.
Code execution in a child process starts from the next instruction following the fork() system call.
fork() system call just creates a seperate address space for the child process therefore it is a cloned copy of the parent process and the child process has all the memory elements of it's parent's process.
Thus, after spawning a child process through fork(), both processes (the parent process and the child process) resumes the execution right from the next instruction following the fork() system call.