我正试图绕过系统调用fork(),我想创建尽可能多的孙子进程。基本上我想要实现的是:
1个父进程 - > 2个子进程 - >每个孩子 - >有两个子进程(总共有4个来自父进程的孙进程)。
parent
/ \
/ \
child1 child2
/ \ / \
/ \ / \
/ \ / \
g.child1 g.child2 g.child3 g.child4
到目前为止,我可以从4个孙子中得到3个,但我也是从一个孙子中得到一个新孩子。这是我到目前为止的输出:
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).
任何提示?
谢谢
#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);
}
}
答案 0 :(得分:4)
首先,创建fork()
将如下所示:
id = fork();
if (id < 0) {
/* error */
exit(1);
}
else if (i > 0) { /* Parent > 0 */
/* parent logic */
}
else { /* Child = 0 */
/* child logic */
}
fork()
将在父进程旁边创建一个子进程。
因此,如果您想匹配您的树(并且基于您现有的代码),流程图将如下所示:
parent : fork()
|--> parent : fork()
| |--> parent
| |--> child_2
|
|--> child_1 : fork()
|--> child_1
|--> sub_child_1
简而言之,您必须在父级和每个新子进程内递归fork()
。
然而,承认分叉过程并不好看。
拥有一个函数可能会更好,让我们说create_child()
,它只从父级派生:
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;
}
答案 1 :(得分:1)
您必须记住子进程和父进程都继续执行相同的代码。当您在lanzanieto(i)
的{{1}}内拨打case 1:
两次时,父母和孩子从第一次拨打main()
(原始父母的孩子和孙子)继续第二次打电话给lanzanieto(i)
,这样两个人都会产生另一个孩子。