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.
Related
In the below program i'm trying to implement these conditions:
I'm trying to only implement the first child process to print “hi”?
and the root process to print “areyou”?
and the final child process must exit from the system without doing anything?
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
pid_t pid1,pid2,pid3,pid4;
int function(){
pid1=fork();
if(pid1>0)
{
cout << "hi" << getpid()<<" " << getppid()<< endl; /*first child process should print "hi"*/
}
pid2=fork();
cout << "hell" << getpid()<<" " << getppid()<< endl;
pid3=fork();
cout << "how " <<getpid() <<" "<<getppid() <<endl;
pid4=fork();
if(pid4>0){
return 0;/* final child process should exit from the system with out doing anything*/
}
else{
cout << "areyou "<<getpid()<<" "<<getppid()<<endl;
}
}
int main() {
/* and the root process should print "are you"*/
function();
}
-with if(pid1>0) i guess i tried to implement first child to output "hi" and i feel i'm lost in understanding how can i get only the root parent process to print "areyou", and how to control the last child to exit with out doing anything
You may do something like
void function()
{
pid_t pid1, pid2, pid3, pid4;
pid1 = fork();
if (pid1 == 0)
{
// first child process should print "hi"
cout << "hi " << getpid() << " " << getppid()<< endl;
}
pid2 = fork();
cout << "hell " << getpid() <<" " << getppid() << endl;
pid3 = fork();
cout << "how " << getpid() <<" "<<getppid() << endl;
pid4 = fork(); // Mostly useless as only parent print something for this one
if (pid1 == 0 && pid2 == 0 && pid3 == 0 && pid4 == 0){
return; // final child process should exit from the system with out doing anything
} else if (pid1 > 0 && pid2 > 0 && pid3 > 0 && pid4 > 0){
cout << "areyou "<< getpid() << " "<< getppid() << endl;
}
}
Demo
with if(pid1>0) i guess i tried to implement first child to output "hi"
No, it's the parent that gets a positive pid (on success), because it gets the process-id of the child it just forked, or -1 if the fork call fails. The child receives a return value of 0.
What you want to do goes like this:
if(pid1 < 0)
{
cout << "fork failed to create a child process."
}
else if (pid1 > 0) // Parent
{
cout << "areyou";
}
else // child
{
cout << "hi";
}
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;
}
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.
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;
}
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;
}