Reputation:
I'm trying to get my head around the system call fork() and I'd like to create as many grandchild processes as I'd like. Basically all I want to achieve is:
1 parent process with -> 2 child processes -> each child -> has two child processes (which are a total of 4 grandchild processes from the parent).
parent
/ \
/ \
child1 child2
/ \ / \
/ \ / \
/ \ / \
g.child1 g.child2 g.child3 g.child4
So far I can get 3 out of the 4 grandchild but I'm also getting a new child from one of the grandchilds. This is the output I'm getting so far:
Process Pid: 5960 PPid: 5958 (position: 1).
Process Pid: 5959 PPid: 5958 (position: 0).
Process Pid: 5962 PPid: 5959 (position: 0).
Process Pid: 5961 PPid: 5960 (position: 1).
Process Pid: 5963 PPid: 5961 (position: 1).
Process Pid: 5964 PPid: 5960 (position: 1).
Any tips?
Thank you
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#define NUM_HIJOS 2
void lanzanieto(int i)
{
int proceso;
proceso = fork();
if (proceso > 0) {
wait(NULL);
} else if (proceso == 0) {
printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
} else if (proceso == -1) {
perror("fallo en fork");
exit(EXIT_FAILURE);
}
}
int main(void)
{
int proceso, i;
for (i=0; i<NUM_HIJOS; i++) {
proceso = fork();
if (proceso == 0) {
switch(i) {
case 0:
printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
lanzanieto(i);
exit(0);
case 1:
printf("Process Pid: %d PPid: %d (position: %d).\n",getpid(),getppid(), i);
lanzanieto(i);
lanzanieto(i);
exit(0);
}
} else if (proceso == -1) {
perror("fallo en fork");
exit(EXIT_FAILURE);
}
}
proceso = wait(NULL);
while (proceso > 0) {
proceso = wait(NULL);
}
/* ************************************* */
if (proceso == -1 && errno != ECHILD) {
perror("fallo en wait");
exit(EXIT_FAILURE);
}
}
Upvotes: 2
Views: 233
Reputation: 1072
Firstly, create a fork()
will look like this :
id = fork();
if (id < 0) {
/* error */
exit(1);
}
else if (i > 0) { /* Parent > 0 */
/* parent logic */
}
else { /* Child = 0 */
/* child logic */
}
fork()
will create a child process along side the parent process.
Therefore, if you want to match your tree (and based on your existing code), the process diagram will look like :
parent : fork()
|--> parent : fork()
| |--> parent
| |--> child_2
|
|--> child_1 : fork()
|--> child_1
|--> sub_child_1
To put it simply, you have to recursively fork()
inside the parent and every new child process.
However acknowledge that forking process that way aren't nice looking.
It could be better to have a function, let's say create_child()
, which fork only from the parent :
parent : create_fork()
|--> parent : create_child()
| |
| |--> parent : create_child()
| | |
| | |--> parent
| | |--> child_3 : do_whatever()
| |
| |--> child_2 : do_whatever()
|
|--> child_1 : do_whatever()
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
void print_pid(char *proc_name)
{
printf("%s: %d\n", proc_name, getpid());
}
int create_child(void)
{
pid_t child_pid = fork();
if (child_pid == 0)
{
print_pid("child");
}
else if (child_pid < 0)
{
perror("create_child");
}
return (child_pid);
}
int make_babies(int babies_number)
{
/* if no baby */
if (babies_number <= 0)
return 0;
/* if baby(ies) */
pid_t child_pid = create_child();
if (child_pid > 0)
{
make_babies(babies_number - 1);
waitpid(child_pid, NULL, 0);
}
return child_pid;
}
int main(void)
{
print_pid("parent");
make_babies(50);
return errno;
}
Upvotes: 4
Reputation: 2454
You must remember that both the child process and the parent process continue executing the same code. When you call lanzanieto(i)
twice in case 1:
in main()
, both the parent and the child from the first call to lanzanieto(i)
(which are the child and grandchild of the original parent) continue on to the second call to lanzanieto(i)
, so both produce another child.
Upvotes: 1