Fork() Parent and Child - c

what I need is to have 3 children and 1 parent (the main program) because the children and parent are going to have diferent functionality.
I don't know why I can't do it properly, as far I have read, when you do a fork(), if it returns 0, you execute the child's code and the parent's code otherwise.
So, this is my program:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char ** argv) {
printf ("Init Parent. PID =%d\n", getpid());
fork();
fork();
if (fork() == 0) {
printf ("Init Child. PID =%d\n", getpid());
sleep(1);
} else {
printf ("I am the parent. PID = %d\n",getpid());
sleep(1);
}
exit(0);
}
This is the output:
Init Parent. PID =9007
I am the parent. PID = 9007
I am the parent. PID = 9009
Init Child. PID =9010
Init Child. PID =9011
I am the parent. PID = 9008
I am the parent. PID = 9012
Init Child. PID =9013
Init Child. PID =9014
And this is what I want:
Init Parent. PID =9007
I am the parent. PID = 9007
Init Child. PID =9010
Init Child. PID =9011
Init Child. PID =9013
Init Child. PID =9014
I don't know why it says I am the parent 3 times and how to do it properly, because 1
if (fork() == 0)
seems bad.
I would really appreciate any help, thank you in advance.

You have to check for parent-child starting from after your first fork. Every time you call fork() you are spawning a child. What you are doing now is this:
Starting executing 1 program (+1 proc, 1 proc total)
First fork(): Main program spawns child (+1 proc, 2 procs total)
Second fork(): Child and main program spawn children. (+2 procs, 4 procs total)
Third fork(): All processes previously mentioned spawn children(+4 procs, 8 procs total).
The resulting process tree from your original code would look like this:
pi
/ | \
pi pi pi
/ | |
pi pi pi
|
pi
Possible solution(works for n-children):
int noProcs = 3;
int i;
for (i = 0; i < noProcs; ++i) {
if (fork() == 0) {
printf("in child\n");
//Do stuff...
exit(0);
}
}
//DONT FORGET: Reap zombies using wait()/waitpid()/SIGCHLD etc...
Note that after every fork() call, the children spawned are executing the same subsequent code. For each step in the loop's iteration, here's what happens after I spawn a child with fork():
Child process: executes child code, and calls exit(). This prevents us from looping and creating more children than intended.
Parent process: Bypasses the if(fork() == 0) statement's body and steps through the loop, spawning additional children as specified.

fork duplicates the process that calls it, creating a new (child) process that is in the exact same state and that continues running at the same point. The only difference between the parent and child is what is returned by the fork call.
So consider what happens with your code. You start with one process:
printf ("Init Parent. PID =%d\n", getpid());
so that one process prints a message
fork();
you fork, so now have two processes (parent and child)
fork();
both processes fork, so you now have 4 processes (parent, 2 children and grandchild)
if (fork() == 0) {
fork again, so you now have 8 processes -- parent, 3 children, 3 grandchildren, and a great-grandchild. Half of them (one child, two grandchildren, and the great-grandchild) have a 0 return from this fork, as they were the children created by this third fork. The other half are parents.
So after these 3 forks, you have 8 processes, 4 of which will print "Init Child" and 4 of which will print "I am the parent"
If you want just 3 direct children (and no grandchildren), you need to arrange your code such that the children do no call fork again. You could use something like:
if (fork() && fork() && fork())
printf ("I am the parent. PID = %d\n",getpid());
else
printf ("Init Child. PID =%d\n", getpid());

Change the code as below.
You need to check on every fork() its return code and not only on the last call of fork. I didn't run and try but this is the error I feel.
You said - you need 1 Parent and 3 child - so during first fork() - 1 child will be created and then for second fork() - 1 grandchild of child and 1 more child of a parent will be created.
EDIT:
parent
/ \
fork-1 fork-2
| |
child1 child-2
|
fork-2
|
child3
for(int i=0;i<2;i++)
{
if (fork()==0)
printf ("Init Child. PID =%d\n", getpid());
sleep(1);
} else {
printf ("I am the parent. PID = %d\n",getpid());
sleep(1);
}
}

Related

Ring of processes using fork() and pipes

I've been wracking my brain about this problem during an hour. I have to create a ring of processes with n processes (quantity is passed as an argument via cmd). The parent process sends his PID to his first child, and this one sends his parent's PID plus his own PID to his next brother, and it happens until we have created n children. After that, the parent process gets the addition of the PID of all his children.
Let's suppose that the parent process' PID is 3400 and we create two children, so the ring is made of three processes
3400 + 3401(first child's PID) + 3402(second child's PID) = 10203
The parent process should get this 10203.
I have thought about one "for" loop in which child processes send the addition of their brothers PID from brother to brother, using only one pipe. Nonetheless, I haven't come across a solution yet.
Given that the task is to use fork() and pipe(), you probably need to use an algorithm like:
Parent creates pipe for it to write to 1st child.
Parent keeps open the write end of pipe to 1st child.
Parent keeps open the read end of the pipe from Nth child.
For each child n = 1..N, Parent creates output pipe for nth child to talk to n+1th.
Parent forks nth child.
nth child closes the write end of its input pipe and the read end of its output pipe.
nth child reads sum of PIDs from input pipe, adds its own pid to the sum, and writes that to the output pipe, then exits.
Meanwhile, Parent closes both ends of the input pipe to the nth (except for the descriptors it must keep open), and loops back to create the n+1th child's pipe and then the child.
When all the children have been launched, parent writes its PID to 1st child and closes the write end of that pipe.
It then reads a response from the Nth child, closes the read end of the pipe, and prints the result.
What is less obvious how you can validate the sum, unless each child also writes its PID to standard output, or the parent (which knows all the child PIDs) computes the answer to verify it.
With zero marks because of the complete lack of error checking:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int N = (argc > 1) ? atoi(argv[1]) : 10;
int c1_wr;
int cN_rd;
int p1[2];
int p2[2];
int pid_chk = getpid();
if (N <= 0 || N >= 100)
N = 10;
pipe(p1);
c1_wr = dup(p1[1]);
printf("%d children\n", N);
printf("Parent = %d\n", pid_chk);
for (int n = 0; n < N; n++)
{
int pid;
pipe(p2);
fflush(stdout);
if ((pid = fork()) == 0)
{
close(p1[1]);
close(p2[0]);
int pid_sum;
read(p1[0], &pid_sum, sizeof(pid_sum));
pid_sum += getpid();
write(p2[1], &pid_sum, sizeof(pid_sum));
close(p1[0]);
close(p2[1]);
exit(0);
}
printf("Child %2d = %d\n", n+1, pid);
pid_chk += pid;
close(p1[0]);
close(p1[1]);
p1[0] = p2[0];
p1[1] = p2[1];
}
cN_rd = p2[0];
close(p2[1]);
int pid_sum = getpid();
write(c1_wr, &pid_sum, sizeof(pid_sum));
close(c1_wr);
read(cN_rd, &pid_sum, sizeof(pid_sum));
close(cN_rd);
printf("PID sum = %d\n", pid_sum);
printf("PID chk = %d\n", pid_chk);
return 0;
}
Sample run:
10 children
Parent = 49686
Child 1 = 49688
Child 2 = 49689
Child 3 = 49690
Child 4 = 49691
Child 5 = 49692
Child 6 = 49693
Child 7 = 49694
Child 8 = 49695
Child 9 = 49696
Child 10 = 49697
PID sum = 546611
PID chk = 546611
The purpose of the fflush(stdout); becomes clear if (a) you omit it and (b) you run the output through a pipeline. It is necessary.
You need some kind of inter process communication (IPC). Commonly used methods for IPC are:
loopback socket
shared memory
You can find all the other methods in wikipedia IPC article.
If you're in control of the behavior of the child processes, and the parent process doesn't have important/hard-to-recreate state before launching the children, you can simplify things.
Instead of an IPC, you can have the parent recursively launch the children detached, terminate itself, and have the last child re-start the parent:
Invoke parent n, where n is number of children to spawn.
parent:
invokes child arg1-1 0 and terminates,
if invoked with "0" for arg1, it adds its own PID to arg2 and you're done, even though in terms of the process tree it's not really a "parent" of anything.
child:
invokes child arg-1 arg2+pid, where pid is child's own PID.
if invoked with "0" for arg1, it invokes parent 0 arg2+pid.

How to get child PID in C?

I'm creating child processes in a for-loop. Inside the child process, I can retrieve the child PID with getpid().
However, for some reason when I try to store the value of getpid() into a variable declared by the parent process, the change is nullified when I check for it in the parent process. I'm assuming this has to do with some sort of process variable scope. Not really familiar with C, so can't be too sure.
Anyhow what is a way of storing the result of getpid() of a child PID (when called from the child process) into a variable in the parent process?
Or maybe another approach is storing fork() into a variable in the parent and calling some function on that variable to retrieve the child's PID? I don't know how to do this either, so if this is the better way, how would you do this?
fork already returns the child's pid. Just store the return value.
look at man 2 fork:
RETURN VALUES
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 indicate the error.
As mentioned in previous answer that "fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process." So, the code can be written in this way:
pid = fork(); /* call fork() from parent process*/
if (0 == pid)
{
/* fork returned 0. This part will be executed by child process*/
/* getpid() will give child process id here */
}
else
{
/* fork returned child pid which is non zero. This part will be executed by parent process*/
/* getpid() will give parent process id here */
}
This link is very helpful and explains in detail.
if fork() is successfully created then it returns 0 value in the child process.
int main(void)
{
int id;
id= fork();
if(id==0)
{
printf("I am child process my ID is = %d\n" , getpid());
}
}
If you are calling fork in the following way:
pid = fork()
Then pid is in fact your child PID. So you can print it out from the parent.
Yes, the child process's pid is already returned with fork(), fork() is called once but return twice, different return value in parent and child process, so you can do this:
pid_t pid, pid_c;
pid = fork();
if (pid == -1) { // error
perror("Falied to fork");
} else if(pid == 0) { // execute in child process
// you can get child's pid by getpid() in child process:
pid_t tmp_pid_c = getpid();
execl("bin/ls", "ls", "./", NULL);
} else {
// you can also get child's pid that already returned by fork() in parent process
pid_c = pid;
}
There are two main functions to get the process id of parent process and child. getpid() and getppid()

output of forking process

hello every one I want to ask a question about forking
here is the code
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#define MAX_COUNT 5
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <= MAX_COUNT; i++) {
sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
printf("child id :%d\n" , pid);
printf("parent id :%d\n" , getppid());
}
and when i run it here is the output
This line is from pid 31130, value = 1
This line is from pid 31130, value = 2
This line is from pid 31130, value = 3
This line is from pid 31130, value = 4
This line is from pid 31130, value = 5
child id :31130
This line is from pid 31131, value = 1
parent id :31052
This line is from pid 31131, value = 2
This line is from pid 31131, value = 3
This line is from pid 31131, value = 4
This line is from pid 31131, value = 5
child id :31131
parent id:31130
it really confused me why
the line parent id and child id printed two times
why child id value is different both time when i have called for
only once
why the second time parent id value is equal to first one child id value
what is actually the parent and chile Id thanks alot
The function fork is called once and returns twice. So both the child and the parent do the printfs.
printf("child id :%d\n" , pid); /* Both child and parent print this. */
printf("parent id :%d\n" , getppid()); /* Both child and parent print this. */
The fact that you say "child" and "parent" doesn't really change anything so that's why you get misleading results.
A common pattern is to test the value returned by fork. It returnss 0 in the child and the PID of the child in the parent.
pid_t pid = fork();
if (pid)
printf("I am the parent, pid: %d. The child has pid: %d\n", getpid(), pid);
else
printf("I am the child, pid: %d\n", getpid());
/* Common code. */
for...
following is the answers of your questions:
When you create a process fork it actually starts one another process
hence after forking everything is executed by the main process as well as the child process so the line parent id and child id printed twice and it given different values both the time because both are executed by different processes so both have different id and different parent id now the answer of your third question is at that time of execution the second process executing the statement so its parent is the previous process so the second time parent id value is equal to first one child id value.
I hope you would be able to understand it.
After fork call parent and child executing same code
that is the reason for getting 4 ids printed
31131 is your child process
31130 its parent
31052 is parent's parent

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.

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