Forking inside if dilemma - c

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?

Related

C - Child Process Not Executing

[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.

Fork tree diagram

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"
}

Trying to understand forks and semaphores

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

How to use fork() in an if statement

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;
}

Controlling Forks in C

I have a C file that looks like this:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
pid_t child_pid;
printf ("The PID is %d\n", (int) getpid ());
child_pid = fork ();
if (child_pid != 0)
{
printf ("this is the parent process, with PID %d\n",
(int)getpid());
printf ("the child's PID is %d\n", (int) child_pid);
}
else
printf ("this is the child process, with PID %d\n",
(int)getpid());
return 0;
}
I need to modify it to produce a a hierarchy that looks like
parent (0)
|
+---> child (1)
|
+---> child (2)
|
+----> child (3)
|
+----> child (4)
|
+----> child (5)
|
Basically a tree structure where each second child makes two new children. As far as I understand it, when I fork() a process, each process will run concurrently. Adding a fork() in the if statement seems to work and creates processes 0 to 2 correctly, since only the parent will create a new fork. But I have no idea how to make process 2 fork and not 1. Any ideas?
Well, process 1 will be created by the first fork. Process 2 will be created by the fork inside the if-statement. So to let process 2 fork too, you fork again inside the if-statement if the second fork did not return 0.
An illustration:
if(fork) {
// Inside process 0
if(fork) {
// still in process 0
} else {
// in process 2
if(fork) {
// still in process 2
} else {
// in prcess 3
}
// and so on
}
} else {
// Inside process 1
}
Children get a copy of the parent's state at the time of the fork.
So if the parent has a counter or other property then the children will see the value at the time of they were forked (but not if the parent subsequently alters it).
I don't know why you want to do it this way, but normally only the parent process performs the fork. This may be easier to design too. When you perform fork() inside a for-loop you'll have direct control over the processes created.
Please be aware that fork() is a relatively expensive operation, especially if you want to create many processes. More lightweight alternatives vfork and threads are available but I can not judge if they also fit your needs.
An old question, but an interesting one still. The man page for fork() tells us that 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 we know that fork() returns a 0 to the child, we can use this as the controlling mechanism:
int main()
{
// Here we're in the parent (0) process
if(fork()) // This starts the chain, only the parent will do this
if(!fork()) //the child will pass this, the parent will skip it
for(count = 0; counter < number_of_processes; counter++) //now the 2nd child loops
{
if(fork())
if(!fork());
else
break;
}
Let's put some numbers to it:
//parent (18402)
if(fork()) // spawns 18403, parent 18402 keeps going
if(!fork()) // spawns 18404, parent 18402 drops to the end of main()
for(count = 0; count < number_of_processes; conter++) // 18404 enters here
if(fork()) // 18404 forks 18405 and then goes on
if(!fork()); // 18404 spawns 18406 before leaving, 18406 restarts the loop
else
break; // 18404 breaks out there
else
break; //18405 leaves the loop here
So after one iteration we have:
18402
|
+---> 18403
|
+---> 18404
|
+----> 18405
|
+----> 18406
|
After this we'll keep looping two new processes, the second of which will keep iterating until you've made as many passes as are required.

Resources