Fork call working - c

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.

Related

saving the returnin value of fork in a variable in C [duplicate]

This question already has answers here:
How does fork() know when to return 0?
(5 answers)
Closed 5 years ago.
I am a bit confused about the value which the function fork returns. I understand that value 0 is for child process and value >0 is for parent process.
I have the code below
int main()
{
int pid;
pid = fork();
if(pid == 0)
//DO SOMETHING
else
//DO SOMETHING ELSE
return 0;
}
The valiable pid after fork is different for each process ?
I can't understand how it switches value. And I have a second part with code
int main()
{
int pid;
if (pid == 0)
{
return 5;
}
printf("parent = %d waits for child = %d ", getpid(), pid);
waitpid(pid, NULL, 0);
printf("child terminates!")
return 0;
}
in which I can't understand why pid on line with first printf has the value of child. It shouldn't be the id of parent ?
The valiable pid after fork is different for each process ?
Yes, that's the new process ID you get as the return value. There can't be same processes with the same ID at the same time, so whenever you fork your usually get an unique one.
The process is cloned while still inside the fork() call, including copies of all variable memory contents (heap, stack, data segments). Once the copy is completed, the kernel resumes execution of both processes, but gives different return values.
in which I can't understand why pid on line with first printf has the value of child. It shouldn't be the id of parent ?
getpid() returns the ID of the parent, since that is the context in which you are executing it now. pid is just garbage (uninitialized memory) in that example, so whatever you think you are seeing, it's not an process ID but only some random memory content.

How to fork and create a specific number of children that perform the same task?

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.

Explain why fork causes the IF condition to behave differently.

I found this sample via a search.
At first glance I thought only the first fork() would be executed based on the IF condition, but actually both fork() calls get executed.
If the fork() command is changed to a simple boolean comparison like (x==10) then the IF conditions behave as expected.
What is it about the fork() that causes the IF condition to behave differently?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
pid_t whichone, first, second;
int howmany;
int status;
int x = 0
if ((first=fork())==0) /* Parent spawns 1st child */
{
printf("Hiya, I am the first child nd my id is %d\n", getpid());
sleep(10);
exit(0);
}
else if (first == -1)
{
perror("1st fork: something went bananas\n");
exit(1);
}
else if ((second=fork())==0) /* Parent spawns 2nd child */
{
printf("Hiya, I am the second child and my id is %d\n", getpid());
sleep(15); /* Sleep 15 sec, then exit */
exit(0);
}
else if (second == -1)
{
perror("2nd fork: something went bananas\n");
exit(1);
}
printf("This is the parent\n");
howmany=0;
while (howmany < 2) /* Wait twice */
{
whichone=wait(&status);
howmany++;
if (whichone==first)
printf("First child exited ");
else
printf("Second child exited ");
if ((status & 0xffff)==0)
printf("correctly\n");
else
printf("uncorrectly\n");
}
return 0;
Here is the output when executed. Notice that both fork() calls are processed.
> runtThis
Hiya, I am the first child, and my id is 31204
Hiya, I am the second child, and my id is 31205
This is the parent
First child exited correctly
Second child exited correctly
The first if detects if its running in the child. If it isn't, but fork() didn't fail (i.e., it didn't return -1), it's in the original process, which can then continue and call fork() again.
Not sure what the confusion is about.
The fork() function duplicates the current process and then returns in both processes. So, effectively, the fork() function returns twice.
In the new process, fork() returns with the value 0, which causes the relevant branch that prints "I am the child" to be taken.
In the original process, fork() returns a non-zero value, indicating either failure (if it is negative) or the process id of the new process (if it is positive). As this value is non-zero, the branch is skipped to the next else if and that test is performed until one succeeds.
In the parent process, none of the if/else if tests will succeed, but each of the fork calls causes a new process to be created in which the corresponding test succeeds and that creates the effects you noticed.

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

What exactly does fork return?

On success, the PID of the child
process is returned in the parent’s
thread of execution, and a 0 is
returned in the child’s thread of execution.
p = fork();
I'm confused at its manual page,is p equal to 0 or PID?
I'm not sure how the manual can be any clearer! fork() creates a new process, so you now have two identical processes. To distinguish between them, the return value of fork() differs. In the original process, you get the PID of the child process. In the child process, you get 0.
So a canonical use is as follows:
p = fork();
if (0 == p)
{
// We're the child process
}
else if (p > 0)
{
// We're the parent process
}
else
{
// We're the parent process, but child couldn't be created
}
p = fork();
/* assume no errors */
/* you now have two */
/* programs running */
--------------------
if (p > 0) { | if (p == 0) {
printf("parent\n"); | printf("child\n");
... | ...
Processes are structured in a directed tree where you only know your single-parent (getppid()). In short, fork() returns -1 on error like many other system functions, non-zero value is useful for initiator of the fork call (the parent) to know its new-child pid.
Nothing is as good as example:
/* fork/getpid test */
#include <sys/types.h>
#include <unistd.h> /* fork(), getpid() */
#include <stdio.h>
int main(int argc, char* argv[])
{
int pid;
printf("Entry point: my pid is %d, parent pid is %d\n",
getpid(), getppid());
pid = fork();
if (pid == 0) {
printf("Child: my pid is %d, parent pid is %d\n",
getpid(), getppid());
}
else if (pid > 0) {
printf("Parent: my pid is %d, parent pid is %d, my child pid is %d\n",
getpid(), getppid(), pid);
}
else {
printf("Parent: oops! can not create a child (my pid is %d)\n",
getpid());
}
return 0;
}
And the result (bash is pid 2249, in this case):
Entry point: my pid is 16051, parent pid is 2249
Parent: my pid is 16051, parent pid is 2249, my child pid is 16052
Child: my pid is 16052, parent pid is 16051
If you need to share some resources (files, parent pid, etc.) between parent and child, look at clone() (for GNU C library, and maybe others)
Once fork is executed, you have two processes. The call returns different values to each process.
If you do something like this
int f;
f = fork();
if (f == 0) {
printf("I am the child\n");
} else {
printf("I am the parent and the childs pid is %d\n",f);
}
You will see both the messages printed. They're being printed by two separate processes. This is they way you can differentiate between the two processes created.
This is the cool part. It's equal to BOTH.
Well, not really. But once fork returns, you now have two copies of your program running! Two processes. You can sort of think of them as alternate universes. In one, the return value is 0. In the other, it's the ID of the new process!
Usually you will have something like this:
p = fork();
if (p == 0){
printf("I am a child process!\n");
//Do child things
}
else {
printf("I am the parent process! Child is number %d\n", p);
//Do parenty things
}
In this case, both strings will get printed, but by different processes!
fork() is invoked in the parent process. Then a child process is spawned. By the time the child process spawns, fork() has finished its execution.
At this point, fork() is ready to return, but it returns a different value depending on whether it's in the parent or child. In the child process, it returns 0, and in the parent process/thread, it returns the child's process ID.
Fork creates a duplicate process and a new process context. When it returns a 0 value it means that a child process is running, but when it returns another value that means a parent process is running. We usually use wait statement so that a child process completes and parent process starts executing.
I think that it works like this:
when pid = fork(), the code should be executed two times, one is in current process, one is in child process.
So it explains why if/else both execute.
And the order is, first current process, and then execute the child.

Resources