Reputation: 61
Hi there I've been working on a program that forks children and later will fork more children from each child but that's not what I need help with. When I run my program (in here it is a function but works the same) I am supposed to have one parent(PPID) spawn 3 children (PIDS= 1,2,3) but what I get is either the same PID and PPID 3 times (my current code) or before I was getting 3 parents with each parent having one child and the PPIDS were different as well as the PIDS, but the PPIDs were just the same as the previous child PIDs. In my latest attempts it never displays the parent(dad) message above the child(son). It should look like this
[dad] hi am I PID 1234 and I come from ####(dont care what this number is)
[son] hi i am PID 1111 and I come from PPID 1234
[son] hi i am PID 1112 and I come from PPID 1234
[son] hi i am PID 1113 and I come from PPID 1234
here is my code. I'm just looking for hints if possible unless it's just a silly mistake I've made like "oh just move the fork() to the child process" or something like that.
Also I have a child_count just so I can easily count the children.
int forking(null)
{
void about(char *);
int i=0;
int j=0;
int child_count =0;
about("dad");
for(i = 0; i < 3; i++ ){
pid_t child = 0;
child = fork();
if (child < 0) { //unable to fork error
perror ("Unable to fork");
exit(-1);}
else if (child == 0){ //child process
about ("son");
printf("I am child #%d \n",child_count);
child_count++;
exit(0);}
else { //parent process (do nothing)
}
}
for(j = 0; j < 3; j++ ){
wait(NULL);//wait for parent to acknowledge child process
}
return 0;
}
Upvotes: 5
Views: 23905
Reputation: 881333
The one thing you have to remember is that, when you fork
, both the parent and child will continue on running the code at that point.
So, if you don't do child/parent detection correctly, the children will most likely start up their own children.
One good way for you to start up three children and no grandchildren is to use a counter in conjunction with the returned process ID from the fork
call, along the lines of the following:
#include <stdio.h>
#include <unistd.h>
#define COUNT 3
int main(void) {
# Desired and actual count.
int count = COUNT, children = 0;
// Force parent initially.
pid_t retpid = 1;
// Only fork if limit not reached AND is parent (children
// will exit loop with retpid == 0).
while (count-- > 0 && retpid > 0)
// Adjust actual count if successful.
if ((retpid = fork()) > 0)
children++;
// Detect parent, all forks returned non-zero.
if (retpid != 0) {
printf("Parent %d spawned %d/%d children\n",
getpid(), children, COUNT);
// Wait for children to finish.
while (children-- > 0)
wait(NULL);
} else {
// Otherwise you were one of the children.
printf("Child %d, sired by %d\n", getpid(), getppid());
}
return 0;
}
This outputs what you seem to be after though, due to the vagaries of scheduling, not necessarily in that order:
Parent 26210 successfully spawned 3/3 children
Child 26212, sired by 26210
Child 26213, sired by 26210
Child 26211, sired by 26210
The checking of the returned PID will ensure only the parent does any forking, and the count will limit it to a specific quantity.
One thing you also need to watch out for is output buffering. When you fork, you may end up with two processes with buffered output data.
Where the output device can be detected to be a terminal, flushing will normally occur on a newline being output, so your printf
calls probably won't duplicate output for a normal run.
You just need to be aware that you may get interesting results if you redirect your output to a file, for example.
Upvotes: 2
Reputation: 34829
The parent needs to
- print a message
- call fork three times
- wait for the three children to exit
Each child needs to
- print a message
- exit
So the code is as simple as
int main( void )
{
printf( "[dad] pid %d\n", getpid() );
for ( int i = 0; i < 3; i++ )
if ( fork() == 0 )
{
printf( "[son] pid %d from pid %d\n", getpid(), getppid() );
exit( 0 );
}
for ( int i = 0; i < 3; i++ )
wait( NULL );
}
which generates this output
[dad] pid 1777
[son] pid 1778 from pid 1777
[son] pid 1779 from pid 1777
[son] pid 1780 from pid 1777
Upvotes: 5