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

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)

Related

How to display the pid of a parent process

let me start by saying this is my first question on stackoverflow, and I am very new to coding as well, so I appolagize in advance for any shortcomings.
I am trying to find out how a child process can display the parent pid of their own parent process (the child process' grandparent pid)
Here is the code I have, I added a comment that I need to change:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int pid, status, status2;
pid = fork();
switch (pid)
{
case -1: // An error has occured during the fork process.
printf("Fork error.");
break;
case 0:
pid = fork();
switch (pid)
{
case -1:
printf("Fork error.");
break;
case 0:
printf("I am the child process C and my pid is %d\n", getpid());
printf("My parent P has pid %d\n", getppid());
printf("My Grandparent G has pid %d\n", //what to put here );
break;
default:
wait(&status);
printf("I am the parent process P and my pid is %d\n", getpid());
printf("My parent G has pid %d\n", getppid());
break;
}
break;
default:
wait(&status2);
printf("I am the Grandparent process G and my pid is %d\n", getpid());
break;
}
}
also, general tips would be appreciated
You could just save the pid in grandparent.
int pid, status, status2;
int pppid = getpid();
pid = fork();
switch (pid) {
....
printf("My parent G has pid %d\n", pppid);
}
or save the pid of getppid() in parent. There is no "standard" way of getting "parent pid of parent pid" so it's just the same as getting pid of any other process. You could inspect /proc/<pid>/stat, something along:
pid_t getppid_of_pid(pid_t pid) {
intmax_t ret = -1;
char *buf;
int r = asprintf(&buf, "/proc/%jd/stat", (intmax_t)pid);
if (r == -1) goto asprintf_err;
FILE *f = fopen(buf, "r");
if (f == NULL) return fopen_err;
if (fscanf(f, "%*s %*s %*s %jd", &ret) != 1) return fscanf_err;
fscanf_err:
fclose(f);
fopen_err:
free(buf);
asprintf_err:
return ret;
}
...
printf("My Grandparent G has pid %jd\n", (intmax_t)getppid_of_pid(getppid()));
See man procfs for explanation of fields in /proc/../stat.

How to visualise fork() in 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.

How to make parent process wait for child processes to finish?

I have an assignment which gives me this code to transform into a code that makes the parent process wait for all children processes to finish.
PS: the first code has 4 processes and needs to use waitpid to solve this.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t p = fork();
pid_t k = fork();
if(p>0){
printf("p=%d: PID = %d\n", p, getpid());
sleep(45);
exit(0);
}
else if(p==0){
printf("p=%d: PID = %d\n", p, getpid());
exit(0);
}
else if(p<0){
printf("ERRO! p=%d\n", p);
exit(p);
}
}
I've tried this, but I think that this only works for only 1 child process and not for a lot of them.
int main(){
pid_t p = fork();
pid_t k = fork();
if(p<0){
printf("fodeu");
exit(p);
}
else if(p==0){
printf("");
exit(0);
}
else{
for(i=0;i<4;i++){
int returnstatus;
waitpid(p,&returnstatus,0);
if(returnstatus == 0){
printf("o processo filho correu normalmente");
}
else if(returnstatus == 1){
printf("o processo filho ardeu");
}
}
}
}
This won't do your assignment, but I hope it is advice enough to get
you going. The assignment appear to be a riddle around fork(), your
teacher has good taste :-)
fork() is different. It returns twice.
In the parent it returns the process ID of the created process.
In the child it returns 0; a process can always determine its PID using getpid()
Actually, the assignment is not good taste. Usually code using `fork()
never lets any branch escape into enclosing code to avoid complete
bullshit. Like so,
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
if (pid == 0 /*child*/) {
printf("PID %d (child) doing work\n", pid);
sleep(5);
exit(0); // don't let it continue (leak) into parent code
}
else if (pid > 0 /*parent*/) {
int status;
pid_t terminated;
printf("PID %d (parent) waiting for child PID %d\n", getpid(), pid);
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid");
exit(1);
}
if (WIFEXITED(status))
printf("child exited normally with status %d\n", WEXITSTATUS(status));
else
printf("hm. child died otherwise. see 'man waidpid' for more\n");
}
return 0;
}
With this in mind, look at these two innocent looking lines,
pid_t p = fork(); // two processes after this
pid_t k = fork(); // executed by **two** processes, again duplicating
So, after these two lines we have four processes executing the rest of
the code in parallel. This is the point where brains explode. What
does the leaked child of the k line do when it asks what p's value
is?
Look at the output of this little program, to see what's the effect of
leaking.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
printf("MAIN PID %d\n", getpid());
fork();
fork();
printf("PID %d, PPID %d\n", getpid(), getppid());
return 0;
}
This is one way to do it; there will be numerous others.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static void wait_for_kids(void);
int main(void)
{
pid_t p = fork();
pid_t k = fork();
if (p > 0)
{
printf("p=%d: PID = %d\n", p, getpid());
sleep(5);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else if (p == 0)
{
printf("p=%d: PID = %d\n", p, getpid());
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(0);
}
else
{
printf("ERROR! p=%d\n", p);
wait_for_kids();
printf("%d: p = %5d, k = %5d - exiting\n", getpid(), p, k);
exit(p);
}
/*NOTREACHED*/
}
static void wait_for_kids(void)
{
int corpse;
int status;
int pid = getpid();
while ((corpse = waitpid(0, &status, 0)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", pid, corpse, status);
}
Example output:
p=43445: PID = 43444
p=43445: PID = 43446
p=0: PID = 43445
p=0: PID = 43447
43447: p = 0, k = 0 - exiting
43445: child 43447 exited with status 0x0000
43445: p = 0, k = 43447 - exiting
43446: p = 43445, k = 0 - exiting
43444: child 43445 exited with status 0x0000
43444: child 43446 exited with status 0x0000
43444: p = 43445, k = 43446 - exiting

Duplicate printf while forking

I'm using fork to make process tree here's the code:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
int main () {
pid_t pid;
printf("Parent of all: %ld\n",(long)getpid());
pid = fork();
if(pid == -1){
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0){
pid = fork();
printf("Child with id: %ld and its Parent id: %ld \n", (long)getpid(),(long)getppid());
if(pid > 0){
pid = fork();
printf("Child with id: %ld and its Parent id: %ld \n", (long)getpid(),(long)getppid());
_exit(EXIT_SUCCESS);
}
}
else{
int status;
waitpid(pid, &status, 0);
}
return EXIT_SUCCESS;
}
after else if the printf line passes to a child so i get the same thing printed twice as u can see in results here results can i somehow prevent this from happening?
When you call fork both the parent and child process will continue executing from the same point, which means they will both execute printf("child with id...).

Forking N processes in chain

I want to solve a certain problem and i can't figure it out how to do it properly. I have to create N processes in chain and after i finish making all of them, the initial process will random a number and write it in the pipe, the other processes read from the pipe the number, they randomize a number and substract the result from the number read, write it back to the pipe and so on. Here is what i've tried
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define P_READ 0
#define P_WRITE 1
void forker(int nprocesses, int** pipes, int fd[2])
{
pid_t pid;
int buf;
if(nprocesses > 0)
{
if ((pid = fork()) < 0)
{
perror("fork");
}
else if (pid == 0)
{
//Child
printf("Child %d created PID : %d , PPID : %d\n", nprocesses-1, getpid(), getppid());
int i = nprocesses - 1;
time_t t;
srand((int)time(&t) % getpid()); // get unique seed for every child
int r = (rand() % 11) + 10;
if (i==0) {
read(fd[P_READ], &buf, sizeof(int));
close(fd[P_READ]);
}else{
read(pipes[i-1][P_READ], &buf, sizeof(int));
close(pipes[i-1][P_READ]);
}
close(pipes[i][P_READ]);
buf -= r;
printf("%d|%d|%d|%d\n", buf, r, getpid(), getppid());
write(pipes[i][P_WRITE], &buf, sizeof(int)); // write
close(pipes[i][P_WRITE]);
printf("Child %d end\n", nprocesses-1);
}
else if(pid > 0)
{
forker(nprocesses - 1, pipes, fd);
}
}
}
int main (void)
{
int status = 0;
srand(time(NULL));
pid_t pid = getpid();
pid_t parent = getpid();
pid_t wpid;
int n, fd[2], buf;
printf("Please enter how many processes you want(between 6 and 15): ");
scanf("%d", &n);
while ( n < 6 || n > 15)
scanf("%d", &n);
int **pipes = (int **)malloc(n * sizeof(int*));
for(int i = 0; i < n; i++) pipes[i] = (int *)malloc(2 * sizeof(int));
printf("I'm parent - my pid is %d\n",pid);
pipe(fd);
for(int i=0; i<n; i++) {
if(pipe(pipes[i])) {
printf("pipe error");
return -1;
}
}
forker(n, pipes, fd);
if(parent == getpid()) {
close(fd[P_READ]);
buf = (rand() % 9001) + 1000;
printf("The initial number is %d created by process with pid : %d\n", buf, getpid());
write(fd[P_WRITE], &buf, sizeof(int));
close(fd[P_WRITE]);
}
while ((wpid = wait(&status)) > 0); // WAIT
if (pid == getpid()) printf("End of parent and my pid was %d\n", pid);
return 0;
}
The output looks something like this :
Please enter how many processes you want(between 6 and 15): 10
I'm parent - my pid is 3827
Child 9 created PID : 3828 , PPID : 3827
Child 8 created PID : 3829 , PPID : 3827
Child 7 created PID : 3830 , PPID : 3827
Child 6 created PID : 3831 , PPID : 3827
Child 5 created PID : 3832 , PPID : 3827
Child 2 created PID : 3835 , PPID : 3827
Child 3 created PID : 3834 , PPID : 3827
The initial number is 1625 created by process with pid : 3827
Child 1 created PID : 3836 , PPID : 3827
Child 4 created PID : 3833 , PPID : 3827
Child 0 created PID : 3837 , PPID : 3827
1609|16|3837|3827
Child 0 end
1589|20|3836|3827
1573|16|3835|3827
Child 2 end
1559|14|3834|3827
Child 3 end
1543|16|3833|3827
Child 4 end
1530|13|3832|3827
Child 5 end
Child 1 end
1511|19|3831|3827
Child 6 end
1498|13|3830|3827
Child 7 end
1488|10|3829|3827
Child 8 end
1470|18|3828|3827
Child 9 end
End of parent and my pid was 3827
The problem is that, i am not sure if the first number is randomed before the processes creation(but that's not the big issue here). The big issue is that the initial process creates all the child processes and it is not "in chain".
First fork you process N times, then generate the random number and pass it to other process.
So put the creation of the random number outside the loop for forking the main process

Resources