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;
}
Related
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.
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);
}
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.
Here is the output ---
Parent: my pid is 4525
Parent: my parent's pid is 3350
parant started- 4525 3350
Before Fork
Before Fork
Child 4526 4525
In parent
---Parent End---
When I try to execute the below code ---
void main(int argc, char *argv[])
{
int status;
pid_t my_pid, parent_pid,child_pid;
my_pid = getpid();
parent_pid = getppid();
printf("\nParent: my pid is %d", my_pid);
printf("\nParent: my parent's pid is %d", parent_pid);
printf("\nparant started- %d %d",my_pid,parent_pid);
printf("\nBefore Fork");
if((child_pid = fork()) < 0 )
{
perror("fork failure");
exit(1);
}
if(child_pid == 0)
{
printf("\n Child %d %d\n",getpid(),getppid());
}
else
{
printf("\nIn parent");
wait(&status);
printf("\n---Parent End---\n");
}
}
Why is the Before Fork is printing twice?? Thanks
It's because you're not flushing the output buffer prior to the fork(). Change to:
printf("\nBefore Fork\n");
or:
printf("\nBefore Fork");
fflush(stdout);
I am creating new processes by forking:
printf("original process = %d\n", getpid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
}
}
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
and I want to print out how many processes I have created. My approach as seen above is not the best way of printing how many processes have been created. So my question is: how can we print how many new processes have been created each time we fork without having some kind of loop?
Each successful call to fork creates a new process, and both the parent and the child return from fork(). The child will get 0 as return, the parent the PID of the child.
printf("I am the root %d\n", getpid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
{
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
}
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
And so on...
The problem in your code is that you are printing the text in some cases without checking the return value of fork(), so these lines will be printed both by the parent and the child. With my code, each process prints just one line, on creation.
As each creates/spawns a child process,
Based on the order in which the fork() is called
Totally 24 child process are created, this is how its done
1st fork(); (has 4 more fork() calls)
2st fork(); (has 3 more fork() calls)
3st fork(); (has 2 more fork() calls)
4st fork(); (has 1 more fork() calls)
So the totall number of child process would be 4! - 1, that is 4x3x2x1 = 24 - 1
23 child process are created