Reputation: 112
I have the following code, which creates the defined number of child threads using fork()
:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUM_THREADS 4
int main()
{
int i;
pid_t pid;
for(i = 0; i < NUM_THREADS; i++){ //Do this equal to the number of threads
pid = fork();//Use this to avoid multiple forking
if(pid == 0){ //If it's a child process
printf("Hello World! Greetings from PID: %ld! :D\n", (long)getpid()); //getpid returns the pid of the process
exit(0); //Exit the process
}else if(pid == -1){
printf("Oh no! Could not fork! :( Exiting!\n");
return 0;
}
}
int status;
for(i = 0; i < NUM_THREADS; i++){
wait(&status);//wait until all the children processes have finished.
}
printf("All done! I am the parent process! My PID is: %ld if you were curious! \n", (long)getpid());
return 0;
}
This was provided to us as an example. Its output is like:
Hello World! Greetings from PID: 118358! :D
Hello World! Greetings from PID: 118359! :D
Hello World! Greetings from PID: 118360! :D
Hello World! Greetings from PID: 118362! :D
What I'd like to do, instead of having 1 parent process with many children, is to have the parent create a child process, which creates a child process, and so on for the defined number of threads. How can I do that?
Upvotes: 2
Views: 1594
Reputation: 107
First, the term "thread" you used is inappropriate in this situation. Fork means "creating process" not "threads".
You can use a recursive solution but you have to remember that each process creating a process should wait for the return status in order to avoid Zombie Process. Without using any shared variable between process you can use a single variable counter that gets incremented for each forking. But once the counter variable reached the max value, the "youngest" process, i mean the last process created should exit, and one by one other process will exit.
Here is a simple code that works fine:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_PROCESS 5
int counter = 0;
void child_func()
{
pid_t pid;
if (counter < NUM_PROCESS) {
counter++;
pid = fork();
if (pid < 0) {
printf("fork failed counter = %d\n", counter);
}
else if (pid == 0) {
printf("Hello world ! Greetings from pid %ld\n", (long)getpid());
if (counter == NUM_PROCESS) {
exit(0);
}
else {
child_func();
}
}
else {
long var = pid;
wait(&pid);
printf("My pid is %ld and i am the parent of %ld child, i exit\n", (long)getpid(), var);
exit(0);
}
}
}
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0) {
printf("Fork failed %d\n", counter);
return -1;
}
if (pid == 0) {
child_func();
}
else {
wait(&pid);
}
return 0;
}
Upvotes: 1
Reputation: 34829
This task is the same as converting an iterative solution to a recursive solution. The first step is to remove the for
loop. And then modify the child code so that each child:
The key is that each child gets a copy of its parent's variables, so if a child updates a count variable, and then forks, the new child will see the updated count.
Upvotes: 2
Reputation: 180181
Your example code uses the return value of fork()
to distinguish between parent and child. It continues to iterate in the parent (supposing that fork()
does not report an error), and it exit()
s without iterating (after emitting some output) in the child. This is perfectly routine.
What you propose to do is not very much different; what you describe mainly just swaps the roles of parent and child. Indeed, you have a simpler job, because each parent only needs to wait()
for one child. It can do that either inside the loop or outside, provided only that if the last child wait()
s then it should expect the call indicate an error on account of that child not having any children of its own. If the parent does not exit()
or return
from inside the loop, however, then it does need to break out instead of iterating further.
Upvotes: 3