Process id of the parent's parent - Linux - c++

I have three processes in a chain: P1 -> P2 -> P3. I would like to be able to print out the id of all three from within the child(P3) process.
So, my question is how do I get the pid of a grand parent(P1) of the grand child(P3) with getppid() and such?
Or am i going to have to resort to storing the pid of each in their own variables for later use(not desireable)?
Thank you for any assistance you can give me. Also, just because, here is my code thus far:
//test_wait.cpp
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
using namespace std;
int main()
{
pid_t pid; //process id
const char *message;
int n;
int exit_code;
std::stack<int> proc_stack;
cout << "Fork program starting\n";
proc_stack.push(getpid());
pid = fork();
switch ( pid ) {
case -1:
cout << "Fork failure!\n";
return 1;
case 0:
pid = fork();
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
case 0:
cout << "Grandchild PID: " << getpid() << endl;
cout << "Parent PID: " << getppid() << endl;
cout << "Grand Parent PID: " << proc_stack.top() << endl;
exit_code = 9;
break;
default:
exit_code = 0;
break;
}
default:
exit_code = 0;
break;
}
//waiting for child to finish
if ( pid != 0 ) { //parent
int stat_val;
pid_t child_pid;
child_pid = wait ( &stat_val ); //wait for child
}
exit ( exit_code );
}
So, I ended up using a stack to store the information. As seen in the above code now.

You need to print pid and ppid when in child case 0: refer this code.
//test_wait.cpp
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
pid_t pid; //process id
const char *message;
int n;
int exit_code;
cout << "fork program starting\n";
pid = fork();
switch ( pid ) {
case -1:
cout << "Fork failure!\n";
return 1;
case 0:
cout << "Child1 finished: PID = " << getpid() << endl;
cout << "Parent PID = " << getppid() << endl;
pid = fork();
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
case 0:
cout << "Child2 finished: PID = " << getpid() << endl;
cout << "Parent PID = " << getppid() << endl;
message = "This is the child\n";
n = 5;
exit_code = 9;
break;
default:
message = "This is the parent\n";
n = 3;
exit_code = 0;
break;
}
default:
message = "This is the grand parent\n";
n = 3;
exit_code = 0;
break;
}
for ( int i = 0; i < n; ++i ) {
cout << message;
sleep ( 1 );
}
//waiting for child to finish
if ( pid != 0 ) { //parent
int stat_val;
pid_t child_pid;
child_pid = wait ( &stat_val ); //wait for child
}
exit ( exit_code );
}
Also you can get ppid from /proc
cat /proc/pid/stat
e.g. for PID #20467:
cat /proc/20467/stat
20467 (abc) S 20137 20467 20125 34818 20467 4202496 1930 5196 22 0 113 162 32 25 20 0 1 0 1701252 14548992 1606 4294967295 4194304 6492552 2076847264 2076842300 694388884 0 0 0 134889479 2151083916 0 0 17 0 0 0 221 0 0
The 20137 in the above (4th field) is the PPID.

Related

How can i Modify this program so that the child process creates another child?

Modify the following program so that the child process creates another child and wait for it. The grand child prints out the id's of itself, its parent and grandparent.
This is what ive tried so far...
//testWait.cpp
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
pid_t pid; //process id
string message;
int n;
int exit_code;
cout << "fork program starting\n";
pid = fork();
switch ( pid )
{
case -1:
cout << "Fork failure!\n";
return 1;
case 0:
message = "This is the child\n";
n = 5;
exit_code = 9;
break;
default:
message = "This is the parent\n";
n = 3;
exit_code = 0;
break;
}
for ( int i = 0; i < n; ++i )
{
cout << message;
sleep ( 2 );
}
//waiting for child to finish
if ( pid > 0 ) //parent
{
int stat_val;
pid_t child_pid;
child_pid = wait ( &stat_val ); //wait for child
cout << "Child finished: PID = " << child_pid << endl;
if ( WIFEXITED ( stat_val ) ) //rerturn true if child terminated normally that is by exit(3)
cout << "child exited with code " << WEXITSTATUS ( stat_val ) << endl; //returns the exit status of the child.
else
cout << "child terminated abnormally!" << endl;
}
/*
if(pid == 0) //child
{
int stat_val;
pid_t gc_pid, pid2;
pid2 = fork();
//gc_pid = fork();
gc_pid = wait ( &stat_val ); //wait for grandchild
if(pid2 == 0)
{
cout << "This is the GrandChild\n";
exit_code = 9;
cout << "GrandChild finished: PID = " << gc_pid << endl;
//cout << "My parent is PID = " << pid;
}
//cout << "GrandChild finished: PID = " << gc_pid << endl;
}
*/
exit ( exit_code );
}
The part of code where i commented out is what ive attempted.
if(pid == 0) //child
{
int stat_val;
pid_t gc_pid, pid2;
pid2 = fork();
//gc_pid = fork();
gc_pid = wait ( &stat_val ); //wait for grandchild
if(pid2 == 0)
{
cout << "This is the GrandChild\n";
exit_code = 9;
cout << "GrandChild finished: PID = " << getpid() << endl;
cout << "My parent is PID = " << getppid()<< endl;
}
cout << "GrandChild finished: PID = " << getpid() << endl;
}

Trace parent process with PID and display it's child and grandchild PID

I managed to output the correct order of process id's for each individual process but my issue is that I can't display the child's PID.
My program is able to print parent's PID, and grandchild's PID. I do see the child's PID but it displays as parent's PID.
How can I compute child's PID and add it to my code? I would like my output to display parent's PID, child's PID, and grandchild's PID.
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
pid_t pid; //process id
const char *message;
int n;
int exit_code;
cout << "\nfork program starting\n";
pid = fork();
switch ( pid ) {
case -1:
cout << "Fork failure!\n";
return 1;
case 0:
pid = fork();
cout << "Parent PID = " << getppid() << endl;
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
case 0:
cout << "Grandchild finished: PID = " << getpid() << endl;
message = "This is the child\n";
n = 5;
exit_code = 9;
break;
}
}
//waiting for child to finish
if ( pid != 0 ) { //parent
int stat_val;
pid_t child_pid;
child_pid = wait( &stat_val ); //wait for child
if (WIFEXITED (stat_val))
cout << "child exited with code " << WEXITSTATUS (stat_val) << endl;
else
cout << "child terminated abnormally!" << endl;
}
exit ( exit_code );
}
it does not seem you are prining the child PID before the 2nd fork()
change:
case 0:
pid = fork();
cout << "Parent PID = " << getppid() << endl;
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
[...]
}
to:
case 0:
cout << "Child PID = " << getpid() << endl;
pid = fork();
cout << "Parent PID = " << getppid() << endl;
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
[...]
}
here, just after the first line, print getpid(), instead of printing it later. Then use pid2 or different identifier, instead of using same pid. That will solve all your problems.
case 0:
pid = fork();
cout << "Parent PID = " << getppid() << endl;
switch ( pid ) {
case -1:
cout << "Fork Failure!\n";
return 1;
case 0:
cout << "Grandchild finished: PID = " << getpid() << endl;//
Why the problem happened? Because only after 'second case 0', that is child of the child your are printing getpid(), which apparently prints grand child's PID. Instead you should try 'default:' which will work for first level child & second level parent (that is not grand child since not pid!=0). Notably you did not allow case for parent. you gave one case for failure (-1) and another for child(0) and none for parent.

How to fork() two processes simultaneously

I made some headway on my program by allowing it to run for a random number of time between 0 and 20 using rand()%20. However, I cannot figure out how to fork() off multiple processes, 2 maximum.
If I understand fork() correctly, I have created 1 parent and 1 child process in my program. The rand1 value in
else if (pid==0) {
mypid = getpid();
cout << "Child pid is " << mypid << "\n";
execlp("./idle","./idle","1",rand1,0); }
in execlp will create and run the ./idle processes for whatever was generated, correct? For example if rand1 == 19, each process, parent and child, will run for 19 seconds before the program finishes, not including the sleep() timers in the code.
Now my main problem is forking two processes so that I'm not simply left with 1 parent and 1 child, but rather 2 parents and 2 children, but running through the program as it currently works.
I'm lost and hopefully some guidance can come from this post's future replies.
Thank you!
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdlib>
#include <time.h>
using namespace std;
using std::cout;
volatile sig_atomic_t keep_going = 2;
void catch_child (int sig)
{ int status, p;
p = waitpid(-1,&status,WNOHANG);
if (p==0) return;
keep_going=0;
cout<<"Child process caught: "<< p <<endl;
return;
}
int main()
{
pid_t pid;
pid_t mypid;
int rand1;
int i;
srand(time(NULL)); //init seed
rand1 = rand()%20; //generates random number 0 - 20
cout << "This is the random number (rand1): " << rand1 << "\n"; //output to see how long
signal (SIGCHLD, catch_child); //when child is sent, run function catch_child
pid = fork();
if (pid<0) {
cout<<"Error\n";
return 0;
}
else if (pid==0) {
mypid = getpid();
cout << "Child pid is " << mypid << "\n";
execlp("./idle","./idle","1",rand1,0);
} else {
mypid=getpid();
cout<<"Parent procss is " << mypid << " and child is " << pid << "\n";
sleep(3);
cout<<"Pausing child " << pid <<" for " << rand1 << " seconds\n";
kill(pid,SIGSTOP);
for (int i=0; i < rand1; i++) sleep(3);
cout<<"Resuming child "<<pid<<"\n";
kill(pid,SIGCONT);
cout<<"Parent process pid is "<<mypid<<" waiting for child to stop\n";
while (keep_going==rand1) sleep(2);
cout <<"Parent knows that Child now done\n";
}
return 0;
} //keep
UPDATE:
Here's a sample run of what appears to be a semi working program. Attached is the code and an image regarding the sample run with the updated code below.
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdlib>
#include <time.h>
using namespace std;
using std::cout;
volatile sig_atomic_t keep_going = 2;
void catch_child (int sig)
{ int status, p;
p = waitpid(-1,&status,WNOHANG);
if (p==0) return;
keep_going=0;
cout<<"Child process caught: "<< p <<endl;
return;
}
int main()
{
pid_t pid;
pid_t mypid;
int rand1;
int i;
srand(time(NULL)); //init seed
rand1 = rand()%20; //generates random number 0 - 20
cout << "This is the random number (rand1): " << rand1 << "\n"; //output to see how long
signal (SIGCHLD, catch_child); //when child is sent, run function catch_child
;
for(int i=0;i<2;i++){
pid = fork();
if (pid<0) {
cout<<"Error\n";
return 0;
}
else if (pid==0) {
mypid = getpid();
cout << "Child pid is " << mypid << "\n";
execlp("./idle","./idle","1",rand1,0); //does rand1 make the processes run for rand1's value?
} else {
mypid=getpid();
cout<<"Parent procss is " << mypid << " and child is " << pid << "\n";
sleep(3);
cout<<"Pausing child " << pid <<" for " << rand1 << " seconds\n";
kill(pid,SIGSTOP); //SIGSTOP acts as a PAUSE
for (int i=0; i < rand1; i++) sleep(3);
cout<<"Resuming child " << pid << "\n";
kill(pid,SIGCONT);
cout<<"Parent process pid is "<<mypid<<" waiting for child to stop\n";
while (keep_going==rand1) sleep(2);
cout <<"Parent knows that Child now done\n";
}
}
return 0;
}

C++ fork() -- creating a "list" of processes

I have a program that creates new processes "one by one". Is it possible to change this code so it creates a "list" of processes – i.e. child 1 being the parent of child 2, child 2 being the parent of child 3, etc.?
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "err.h"
using namespace std;
int main ()
{
pid_t pid;
int i;
cout << "My process id = " << getpid() << endl;
for (i = 1; i <= 4; i++)
switch ( pid = fork() ) {
case -1:
syserr("Error in fork");
case 0:
cout << "Child process: My process id = " << getpid() << endl;
cout << "Child process: Value returned by fork() = " << pid << endl;
return 0;
default:
cout << "Parent process. My process id = " << getpid() << endl;
cout << "Parent process. Value returned by fork() = " << pid << endl;
if (wait(NULL) == -1)
syserr("Error in wait");
}
return 0;
}
If you want to keep the loop in order to dynamically set the depth of the fork tree,
// Set DEPTH to desired value
#define DEPTH 4
int main ()
{
pid_t pid;
int i;
cout << "My process id = " << getpid() << endl;
for (i=1 ; i <= DEPTH ; i++) {
pid = fork(); // Fork
if ( pid ) {
break; // Don't give the parent a chance to fork again
}
cout << "Child #" << getpid() << endl; // Child can keep going and fork once
}
wait(NULL); // Don't let a parent ending first end the tree below
return 0;
}
Output
My process id = 6596
Child #6597
Child #6598
Child #6599
Child #6600
Use fork in a set of nested ifs
#include<stdio.h>
int main()
{
printf("Parent PID %d\n",getpid());
if(fork()==0)
{
printf("child 1 \n");
if(fork()==0)
{
printf("child 2 \n");
if(fork()==0)
printf("child 3 \n");
}
}
return 0;
}
Output
Parent PID 3857
child 1
child 2
child 3
For n processes,
#include<stdio.h>
void spawn(int n)
{
if(n)
{
if(fork()==0)
{
if(n)
{
printf("Child %d \n",n);
spawn(n-1);
}
else
return;
}
}
}
int main()
{
printf("Parent PID %d\n",getpid());
int i=0;
spawn(5);
return 0;
}
int make_proc(int counter, int parent){
pid_t x=getpid();
std::cout << counter << " process "<< x << " : parent" << parent<< std::endl;
if (counter==0) {
return 1;
}
else {
counter=counter-1;
pid_t pid=fork();
if (pid==0) return make_proc(counter, x);
wait(NULL);
}
}
--------------------
int main(int argc, char **argv)
{
int x=getpid();
make_proc(10, x);
return 0;
}

fork mulitple child in one parent

I want to fork three child process in one parent.
And the following is my C++ code:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
int main()
{
pid_t pid;
for (int i = 0; i < 3; i++)
{
pid = fork();
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0)
cout << "Child " << getpid() << endl;
else
{
wait(NULL);
cout << "Parent " << getpid() << endl;
return 0;
}
}
}
Now my output is :
Child 27463
Child 27464
Child 27465
Parent 27464
Parent 27463
Parent 27462
How should I modify my program to get the output like the following?
Child 27463
Child 27464
Child 27465
Parent 27462
What I mean is that these THREE children need to belong to the same ONE parent, can anybody give me some suggestion ?
Thank you all. :)
You should exit the execution of the child processes. Otherwise, they continue forking also
pid_t pid;
for(i = 0; i < 3; i++) {
pid = fork();
if(pid < 0) {
printf("Error");
exit(1);
} else if (pid == 0) {
cout << "Child " << getpid() << endl;
exit(0);
} else {
wait(NULL);
cout << "Parent " << getpid() << endl;
}
}
There are two issues:
children zero and one continue with the for loop, spawning further processes;
the "parent" branch terminates instead of continuing with the loop.
The following will produce the output you want:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;
int main()
{
pid_t pid;
for (int i = 0; i < 3; i++)
{
pid = fork();
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0) {
cout << "Child " << getpid() << endl;
return 0;
} else {
wait(NULL);
if (i == 2) {
cout << "Parent " << getpid() << endl;
}
}
}
}
When I run it, I get
Child 4490
Child 4491
Child 4492
Parent 4489
Move your return 0 from the last condition to the middle one:
if (pid < 0)
{
cout << "Fork Error";
return -1;
}
else if (pid == 0) {
cout << "Child " << getpid() << endl;
return 0;
}
else
{
wait(NULL);
cout << "Parent " << getpid() << endl;
}
This way the parent will continue to loop, and the children will terminate instead of looping.