Creating of specific process tree - c

I'm trying to create a process tree as on image. Down below is my code, that i wrote. It works properly but only a half. The output of my code is on the second screenshot. The problem is, that i don't know, how to make the last generation.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int i;
int j;
pid_t ppid;
pid_t cpid;
ppid = getpid();
printf("I'm the parent, my PID is: %d\n", ppid);
for (i = 0; i < 4; i++) {
ppid = fork();
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
for(j = 0; j < 2; j++) {
ppid = fork();
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}
}
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}
}
sleep(1);
printf("I'm process %d. Waiting for one of my children to complete", getpid());
wait(NULL);
printf("Eltern: I'm done\n");
printf("... and bye. \n");
}

If I understand your question correct, you just need to add a fork in the inner most if-statement.
if (ppid == 0) {
printf("Hello, my PID is: %d, my parent's PID is %d\n", getpid(), getppid());
// Add one more fork here
sleep(60);
printf("I'm process %d and I'm done\n", getpid());
exit(0);
}

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

Displaying process tree in last child

I want to create a tree of processes like the one on the picture. The Z process should display the whole tree after seconds given as program argument and I need to handle proper destruction of tree. Additionally, I can't use sleep() command. Program output should look like that:
I’m the process arb: my pid is 751
I’m the process A: my pid is 752. My father is 751
I’m the process B: my pid is 753. My father is 752, grandfather 751
I’m the process X: my pid is 754. My father is 753, grandfather 752, great-grandfather is 751
I’m the process Y: my pid is 755. My father is 753, grandfather 752, great-grandfather is 751
I’m the process Z: my pid is 756. My father is 753, grandfather 752, great-grandfather is 751
//wait some seconds and display process tree
I am Z (755) and I die
I am Y (755) and I die
I am X (754) and I die
I am B (753) and I die
I am A (752) and I die
I am arb (751) and I die
After getting to last child and raising alarm it doesn't display the process tree and starts to create some new processes instead of killing them. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
int arb;
void z_function() {
printf("pstree\n");
execl("/bin/pstree", "pstree", "-p", arb, (char*)0);
printf("I am Z (%d) and I die\n", getpid());
kill(getpid(), SIGKILL);
}
int main(int argc, char **argv) {
signal(SIGALRM, z_function);
int arg = atoi(argv[1]);
printf("arg: %d\n", arg);
arb = getpid();
printf("I'm the process arb: my pid is %d\n", getpid());
//A
if (fork() == 0) {
int a = getpid();
printf("I'm the process A: my pid is %d. My father is %d\n", getpid(), getppid());
//B
if (fork() == 0) {
int b = getpid();
printf("I'm the process B: my pid is %d. My father is %d, grandfather %d\n", getpid(), getppid(), arb);
int children[3];
for (int i = 0; i < 3; i++) {
if (fork() == 0) {
children[i] = getpid();
switch(i) {
case 0:
printf("I'm the process X: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
wait(NULL);
break;
case 1:
printf("I'm the process Y: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
wait(NULL);
break;
case 2:
printf("I'm the process Z: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
alarm(arg);
pause();
//exit(0);
break;
}
}
else {
wait(NULL);
}
}
wait(NULL);
kill(children[1], SIGKILL);
printf("I am Y (%d) and I die\n", children[1]);
kill(children[0], SIGKILL);
printf("I am X (%d) and I die\n", children[0]);
printf("I am B (%d) and I die\n", getpid());
exit(0);
}
wait(NULL);
printf("I am A (%d) and I die\n", getpid());
exit(0);
}
else {
wait(NULL);
printf("I am arb (%d) and I die\n", getpid());
exit(0);
}
while (wait(NULL) > 0)
exit(0);
return 0;
}

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

Creating three children in C that have the same parent

My problem is that the children does not have the same parent and does not appear correctly, here is my code:
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid[3];
pid[0] = fork();
if(pid[0] == 0)
{
/* First child */
pid[1] = fork();
if(pid[1] == 0)
{
/* First child continued */
printf("Hello, I'm the first child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
else
{
/* Second child */
pid[2] = fork();
if(pid[2] == 0)
{
/* Second child continued */
printf("Hello, I'm the second child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
else
{
/* Third child */
printf("Hello, I'm the first child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
}
}
else
{
/* Parent */
sleep(1);
wait(0);
printf("Hello, I'm the parent! My PID is : %d, My PPID is: %d", getpid(), getppid());
}
return 0;
}
As of right now when i run the program i will get this as output in bash, where bash has the PID of 11446:
>Hello, I'm the third child! My PID is: 28738, My PPID is: 28735
>Hello, I'm the first child! My PID is: 28742, My PPID is: 28738
>Hello, I'm the second child! My PID is: 28743, My PPID is: 28738
>Hello, I'm the parent! My PID is: 28753, My PPID is: 11446
How do i get the first child to appear first, second child to appear second and the third child to appear last, and get all the children to have the PPID 28753
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.
Your if-else conditions are swapped.

Resources