Ok so I am going through past papers and I am stuck on a question about fork() function here is the diagram I am supposed to recreate using C.
I understand that fork() returns 0 to the child and the childs PID to the parent, but it's really hard to get my head around how exactly this all works.
I have come up with the following but I don't think it works:
while(fork() == 0) {
if (fork() == 0) break;
}
Any help would be appreciated.
Debugging your current code:
while(fork() == 0) {
This line creates a child process (we'll call it child process 1). The parent's process does not enter into the while loop. Child process 1 enters the loop.
if (fork() == 0) break;
This line is now being executed by child process 1, forking from it to create child process 2. If we are currently executing child process 2 (the 'child' of this fork call), we break. If we are executing child process 1, we will continue the next iteration of the while loop.
Now we have the following process tree:
. p
/
. child process 1
/
. cp2
Executing the while loop with child process 1 follows the same pattern as when we passed in parent, resulting in:
. p
/
. child process 1
/ \
. cp2 . cp3
/
. cp4
Solution:
Our end goal is to create 2 child processes, and continue forking from the second child process.
while (1) {
pid_t c1 = fork();
assert(c1 >= 0); // check fork error
if (c1 == 0) break; // don't make more children from c1
pid_t c2 = fork();
assert(c2 >= 0);
if (c2 > 0) break; // don't make additional children from parent
}
If you want to create two children processes from each child2 (and initial parent):
#define MAX 6
int value;
unsigned u = 0;
do{
if((value = fork()) == 0) // child1
break;
else if(value < 0) // error
break;
// parent
if((value = fork()) > 0) // parent
break;
else if(value < 0) // error
break;
// child2
u++;
}while(u < MAX);
if you don't want to set a MAX, use while(1).
Your program didn't create child1 for the first parent.
Write your code and add boxes for variable values on a sheet of paper and execute it by hand. Each time fork() is called:
make a photocopy of your sheet,
on the original give some unique non negative value for the return of fork,
on the copy give 0 to the returned value of fork,
continue to execute instructions on all sheet of paper in any order you want.
This is a good way to understand what will happen.
You are on the right track, in that you need to create new processes in a loop. But the way I think that image mean is that you should let the original parent keep creating processes inside an infinite loop, and the child (all siblings) do their work and exits.
There is also a problem with that image, in that a fork call doesn't really create two children, only one child and then the parent continues, which means that "child2` in that image is really all just the "parent".
So to implement something to create that tree I would do something like
for (;;)
{
int ret = fork();
if (ret == 0)
{
// In the child, "child1" in the image
// Do whatever is supposed to be done
exit(0); // Exit the child
}
else if (ret == -1)
{
// Error, handle it somehow
}
else
{
// In parent, what is called "child2" in the image
// Do something useful here...
// Then wait for the child to exit
wait(NULL);
}
// Let the loop iterate, to create a new "child1"
}
Related
Last created First finished. My teacher said "Modify the code to processes finish in reverse order".
I just started with the exercise. I don't know how to implement so that the processes are executed backwards. My solution would be make a pid processes array and then use waitpid. Like this:
for(int i = num_processes;i>=0;i--){
waitpid(pid_list[i],NULL)
}
Teacher´s code
Finish order
thanks for helping!
The question I linked has been deleted due to it being too unclear, allow me to repost the answer here! Hopefully it helps you out!
//This is NODE 1
int pid = fork();
if(pid == -1){ // Something went wrong
//Handle error
}else if(pid == 0){ // This is the child process == NODE 2
int pid2 = fork();
if(pid2 == -1){ // Something went wrong
//Handle error
}else if(pid2 == 0){ // This is the child process == NODE 3
// Do whatever you want done on Node 3, and have it finish.
}else{ //This is NODE 2
wait(NULL); // Waits for node 3 to finish
}
}else{ //This is the parent process
//You can either do waitpid like you mentioned, or simply do wait NULL and it will wait for a process to finish
wait(NULL);
}
Of course if this were to go on with more nodes, I'd recommend a recursive approach since the code is exactly the same.
You mentioned the teacher showed you the code with the loop and the waitpid, the issue there is that if you want the parent to wait for all the processes, they should all hang from this same parent, instead of having a "tree-like" structure where every parent node waits for the child to finish before ending.
If you do indeed want one node to have all the children, you can do a loop where you create the forks like the one on the screenshot, exiting the loop whenever the result from the fork is a child process instead of the parent itself. Finally, waiting for all the children you created outside the loop, but only if you are the parent process. Something like this:
for(int i=0; i<N_NODES ;i++){
pid = fork();
if(pid == 0){
break; // You exit the loop so that the child doesn't create even more processes
}
}
if(pid != 0){
for(int i=0; i<N_NODES ;i++){
wait(NULL); //You can do wait NULL, or store the different pids when creating the fork and wait for individual pids.
// The issue here would be that you do not know which process finishes first, you can guess, but guessing is never good when programming
}
}
Hope this is what you wanted and I could help! ;)
I need to write a C program that calls fork() a given number of times. Each child process needs to perform the same task (adding some random numbers until a given sum is reached). The parent process waits until all of the child processes have exited. I have written the following code but my output shows that another child doesn't start executing its code until the first one is done.
for (i = 0; i < num_forks; i++) {
child_pid = fork();
if (child_pid < 0) {
perror("fork\n");
} else if (child_pid == 0) {
childProcess(i, goal);
} else {
parentProcess();
}
}
EDIT: The objective is to have all of the child processes run simultaneously. The parent waits for any of the child processes to exit. As soon as any one child process exits, the parent process prints the pid of the child that exited. The remaining child processes continue to run simulatenously until another child exits and so on. If I call parentProcess() outside of the loop, the parent only prints the exiting child pid when the last child process exits.
You need to move the call to parentProcess() outside the loop:
for (i = 0; i < num_forks; i++) {
child_pid = fork();
if (child_pid < 0) {
perror("fork\n");
} else if (child_pid == 0) {
childProcess(i, goal);
}
}
parentProcess();
Otherwise, the parent waits for each child in turn before running the next.
You should be using wait() or waitpid() in a loop inside parentProcess() to collect all the children as they die — and you may do well to provide num_forks as an argument to parentProcess(). Or you need to redefine what you want done. The question suggests that you want the children running simultaneously, while the parent waits for them all to die. That means you have to launch all the children before waiting for them — subject to not running out of processes (so num_forks is a sane number like 20, not an insane number like 2,000 or 2,000,000).
So, your code in parentProcess() should be roughly like this, as a basic minimum:
void parentProcess(void)
{
int status;
int corpse;
while ((corpse = wait(&status)) != -1)
printf("%5d: 0x%.4X\n", corpse, status);
}
And this should be called outside the loop. If called inside the loop, the parent will launch one child, wait for it to finish, then repeat the process. I assume that the childProcess() function never returns; it will lead to chaos if it does return.
What happens if I call:
if (fork() == fork())
//do something
Do both parents and both children enter the statement or what's the procedure in this case?
With two forks, you'll end up with four processes: one parent, two children, and one grandchild.
The order that the two forks happen isn't defined since C doesn't require expressions to be evaluated left to right. In the end it won't matter which happens first, so let's pretend the left fork() happens first. When that happens you'll end up with one parent and one child. The parent will get the child's PID back, and the child will get 0.
Let's call the parent A and the child B. Here's what those two processes will look like after the left fork executes:
A if (<pidof B> == fork())
|
+--B if (0 == fork())
Now each of them will execute the right fork. Two processes become four. Let's call B's new child C and A's new child D. Again, each fork() call will return one of two values: the new child's PID in the parent process, or 0 in the child process. Here's what our four processes will then become:
A if (<pidof B> == <pidof D>)
|
+--B if (0 == <pidof C>)
| |
| +--C if (0 == 0)
|
+--D if (<pidof B> == 0)
As it happens, process C will be the only one that passes the if check.
Try this experiment:
#include<stdio.h>
#include <unistd.h>
int main(void)
{
printf("beginning\n");
if(fork() == fork())
{
printf("two are equal\n");
}
printf("done\n");
return 0;
}
One process prints "beginning", four print "done" and one prints "two are equal". Does this clear things up?
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.
I have to construct a tree of processes using fork() in C. I get a sequence of numbers from standard input (for example: 1 5 0 3) and those numbers tell me how many children each node has. If we take the example then the root process creates 1 child, then this one child creates 5 children of its own, then from those 5 children the first one doesn't create any children, the second one creates 3 of them and then we're done. After this is complete the root process calls pstree that draws out the tree.
Here is a picture of the example:
My question is how can I make new children from a specific node? One needs to create 0 new processes and the next one needs to create 3 of them. I don't know how to distinguish so that only that specific child makes new children and not all of them. Also I'm not sure how to use pstree, because the tree is normally already gone when pstree gets called. I know I can wait() for children to execute first but last ones do not have any children to wait for so they end too fast.
I've written code that creates the example. Need ideas how to generalize this for different inputs. Also can someone show me how to call pstree from this code because I can't seem to get it working.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid;
pid_t temppid;
pid_t temppid2;
int root_pid;
int status;
root_pid = getpid();
pid = fork(); // creates a child from root
if (pid == 0) { // if child
pid = fork(); // fork again (child#1)
if (pid != 0) { // if not child of child#1
temppid = getpid(); // get pid
if (getpid() == temppid) { // create child#2
pid = fork();
if (pid == 0) {
temppid2 = getpid();
if (getpid() == temppid2) { // create child#1
fork();
}
if (getpid() == temppid2) { // create child#2
fork();
}
if (getpid() == temppid2) { // create child#3
fork();
}
}
}
if (getpid() == temppid) { // create child#3
fork();
}
if (getpid() == temppid) { // create child#4
fork();
}
if (getpid() == temppid) { // create child#5
fork();
}
}
}
else {
// create another child from root
pid = fork();
if (pid == 0) {
// run pstree in this child with pid from root
}
}
while (1) {
sleep(1);
}
}
For pstree, the solution is simple - every process, after doing what it should, would go to sleep (for, say, a minute).
Then you can use pstree to see what's going on.
For forking the right number of times, it seems that the problem is with parsing the input, not with forking.
I'd start with writing code that reads the input and, instead of forking, just prints the tree of processes you want to create. Once you have this clear, it shouldn't be able to do the forks right.
For just testing the hierachy your app created:
Instead of placing a
return 0;
as last statement put a
while (1)
sleep(1);
This make the process run for ever until you press Ctrl-C.
After you started the app use another terminal and issue a pstree to inspect the process hierachy the app created.
To clean up (and if on linux) issue a killall <app name>.
My one suggestion is that you use the return value of fork to tell if your code is running in the child process or parent process.