How to visualise fork() in c - c

So I'm currently learning the fork() system call in C but I just can't seem to wrap my head around what exactly is happening.
This is the code
int id=fork();
int child_id, status;
//if id == 0 we are in the child process
if(id == 0 )
{
int pid = getpid()
printf("this is the child process %d\n", pid);
int id1=fork()
if(id1==0)
{
//this will return the pid of the grandparent
int pid2 = getppid();
printf("this is child no 2 process %d\n", pid2);
}
else
{
child_id = wait(&status);
printf("this is parent(%d) of child no 2\n", pid)
}
}
else
{
child_id = wait(&status);
printf("this is the parent process and we will execute after child %d\n", child_id);
}
And this is how I am visualizing it.

Related

How can I create three child processes by a child process?

I want to create three child processes from a child process of the main process (P0). So something like -->
P0 -> P1 ->P2
->P3
->P4
However, whenever I run it I get (for the processes P2,P3,P4) the ppid of the main process (ppid = 1).
I am using fork() system call in order to create the children and the implementation of the program is in C.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i, pid1, pid2;
pid1 = fork();
printf("Pid1 pid -> %d ppid -> %d\n",getpid(),getppid());
if(pid1 != 0)
{
pid2 = fork();
printf("Pid2 pid -> %d ppid -> %d\n",getpid(),getppid());
if(pid2 == 0)
{
for(i=2; i<5; i++)
{
//if(fork()==0)
//{
printf("Child %d pid -> %d Parent -> %d\n",i+1,getpid(),getppid());
//}
exit(0);
}
}
else
{
printf("Pid2 father process \n");
}
}
else
{
printf("Pid1 child process\n");
}
}
You want something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i, pid1, pid2;
pid1 = fork();
printf("Pid1 pid -> %d ppid -> %d\n",getpid(),getppid());
// parent
if(pid1 != 0)
{
pid2 = fork();
printf("Pid2 pid -> %d ppid -> %d\n",getpid(),getppid());
if(pid2 == 0)
{
for(i=2; i<5; i++)
{
if(fork()==0)
{
printf("Child %d pid -> %d Parent -> %d\n",i+1,getpid(),getppid());
// some functionality here
exit(0);
}
}
exit(0);
}
else
{
printf("Pid2 father process \n");
}
}
else
{
printf("Pid1 child process\n");
}
}
Giving the following output in my machine:
Pid1 pid -> 17764 ppid -> 32242
Pid1 pid -> 17765 ppid -> 17764
Pid1 child process
Pid2 pid -> 17764 ppid -> 32242
Pid2 father process
Pid2 pid -> 17766 ppid -> 17764
Child 3 pid -> 17767 Parent -> 17766
Child 4 pid -> 17768 Parent -> 17766
Child 5 pid -> 17769 Parent -> 17766
Thus, with the following hierarchy:
Parent (pid: 17764) -> C1 (17765) -> C2 -> 17666
C3-> 17767
C4-> 17768
C5-> 17769
Warning, in
pid1 = fork();
printf("Pid1 pid -> %d ppid -> %d\n",getpid(),getppid());
the printf is done both in P0 and P1, this is unclear at all, you have first to check pid1 before to print where you are.
Warning, in
pid1 = fork();
...
if(pid1 != 0)
{
pid2 = fork();
you supposed to be in P1 when you fork again, but you are still in P0 because pid1 is not 0
It is also recommended to check fork success (return value is not -1), and wait for the child(ren) termination rather than to exit the parent process before
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int pid1 = fork();
if (pid1 == -1)
perror("cannot fork p1");
else if(pid1 != 0)
{
int pid2;
printf("In P1, Pid1 pid -> %d ppid -> %d\n", getpid(), getppid());
pid2 = fork();
if (pid2 == -1)
perror("cannot fork p2");
else if (pid2 == 0) {
int pid3[2];
int i;
printf("in P2, Pid2 pid -> %d ppid -> %d\n", getpid(), getppid());
for (i = 0; i != 2; ++i) {
pid3[i] = fork();
if (pid3[i] == -1)
perror("cannot fork P2 child");
else if (pid3[i] == 0) {
printf("in Child %d pid -> %d Parent -> %d\n",i+1,getpid(),getppid());
return 0;
}
else
puts("in p2");
}
waitpid(pid3[0], 0, 0); /* erroned if fork failed, whatever */
waitpid(pid3[1], 0, 0); /* erroned if fork failed, whatever */
}
else {
puts("still in p1");
waitpid(pid2, 0, 0);
}
}
else
{
puts("in P0");
waitpid(pid1, 0, 0);
}
return 0;
}
Compilation and execution :
/tmp % ./a.out
In P1, Pid1 pid -> 68995 ppid -> 54669
in P0
still in p1
in P2, Pid2 pid -> 68997 ppid -> 68995
in p2
Child 1 pid -> 68998 Parent -> 68997
in p2
Child 2 pid -> 68999 Parent -> 68997
/tmp %
Note the written pid are wrong, from the manual of getppid :
then a call to getpid() in the child will return the wrong value (to be precise: it will return the PID of the parent process)

Parent process to monitore and fork new child processes depending on exit status

I've created the below code:
int main(int argc, char *argv[])
{
int i, n, N;
pid_t pid;
int status;
N = atoi(argv[1]);
for(i = 0; i < N; i++) {
pid = fork();
if(pid==0) {
srand(getpid() * getppid());
n = rand() % 10 + 1;
printf("I'm child nÂș %d with childpid %d, parent pid = %d, n = %d\n", i, getpid(), getppid(), n);
exit(n);
}
}
while ((pid = waitpid(pid, &status, 0))) {
if (pid < 0)
;
else if (WEXITSTATUS(status) < 4)
printf("exit status %d lower than 4\n", WEXITSTATUS(status));
}
wait(NULL);
return 0;
}
The idea is a parent process forking N child process and each of them exiting with a random value. I want my parent process to monitor all the child processes and fork a new child if the exit status is, for instance <4. This will be going on until all process exit with a status >= 4.
Solved creating a function copying the code from parent and child (keeping the code in main() untouched). The parent calls the function, the function forks another process, and the parent in the same function calls the function recursively under the conditions we choose.

Sending Randomly generated Value from child process to parent process

I have written a code that generates a random number in the child process using rand()... I need to send this random value to the parent process using pipe(). when I use read() and write () the values received by the parent is 0 instead of the random number.
I am getting no error just the output is Value received is : 0.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<fcntl.h>
int main ()
{
pid_t Cpid;
int fd[2];
int rVal;
//pid will store the value of fork()
Cpid = fork();
pipe(fd);
if( Cpid == 0)
{
//CHILD
rVal = rand()%100;
;
//this is in child process
close (fd[0]);
rVal = rand()%100;
write(fd[1], &rVal,sizeof (rVal));
close (fd[1]);
printf(" Child Pid : %d sending random value : %d to parent : %d\n",
getpid(), rVal, getppid());
}
else if(Cpid != 0 )
{
printf (" Parent PID : %d\n", getpid());
//this is the parent process
close(fd[1]);
read(fd[0], &rVal, sizeof(rVal));
printf(" value recieved is : %d\n", rVal);
close(fd[0]);
printf(" value recieved by parent : %d\n", rVal);
}
return 0;
}
The code should setup the pipe before forking the children. Otherwise, the parent and the children will use different pipes, and will not be able to talk to each other.
int main ()
{
pid_t Cpid;
int fd[2];
// Create the pipe BEFORE forking.
pipe(fd);
//pid will store the value of fork()
Cpid = fork();
if( Cpid == 0)
.. REST OF CODE ~~~

Parent/Child process print

I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.

getting child process ID from the parent using C

I'm trying to write a C program where I have one parent that create two childs.
My task is to retrieve the process ID of the parent of and both childs. For this I've been using getpid().
Now I've been asked to get the child information from the parent. I don't get how I can do this. Like how can I obtain the processing ID for a child from the parent?
I have this at the moment (simplified)
fork1 = fork();
if (fork1 < 0)
fork error
else if (fork1 == 0) {
child 1
use getpid()
use getppid()
} else {
fork2 = fork();
if (fork2 < 0)
fork error
else if (fork2 == 0) {
child 2
use getpid()
use getppid()
} else
parent again
}
After a minute of googling I found this page, where everything you need is written:
System call fork() is used to create processes. It takes no arguments and returns a process ID.
I highlighted the part which is importand for you, so you don't need to do anything to get the process IDs of the children. You have them already in fork1 and fork2!
Here is some code which will print the PIDs from parent and children.
#include <stdio.h>
int main() {
int fork1 = fork();
if (fork1 < 0) {
printf("error\n");
} else if (fork1 == 0) {
printf("I'm child 1\n");
printf("child 1: parent: %i\n", getppid());
printf("child 1: my pid: %i\n", getpid());
} else {
int fork2 = fork();
if (fork2 < 0) {
printf("error\n");
} else if (fork2 == 0) {
printf("I'm child 2\n");
printf("child 2: parent: %i\n", getppid());
printf("child 2: my pid: %i\n", getpid());
} else {
printf("I'm the parent\n");
printf("The PIDs are:\n");
printf("parent: %i\n", getpid());
printf("child 1: %i\n", fork1);
printf("child 2: %i\n", fork2);
}
}
return 0;
}
fork() returns two different values, it returns zero to the child and returns non-zero positive value to the parent, this value is the child process ID, so in your last else, fork1 is the pid of child1 and fork2 is the pid of child2.

Resources