2012-06-06 36 views
17

我开始学习一些C,并在研究fork时等待函数,我得到了意想不到的输出结果。至少对于我来说。如何使用Fork()仅创建2个子进程?

有没有什么办法从父母只创建2个子进程?

这里我的代码:

#include <sys/types.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/wait.h> 

int main() 
{ 
    /* Create the pipe */ 
    int fd [2]; 
    pipe(fd); 

    pid_t pid; 
    pid_t pidb; 


    pid = fork(); 
    pidb = fork(); 

    if (pid < 0) 
    { 
     printf ("Fork Failed\n"); 
     return -1; 
    } 
    else if (pid == 0) 
    { 
     //printf("I'm the child\n"); 
    } 
    else 
    { 
     //printf("I'm the parent\n"); 
    } 

    printf("I'm pid %d\n",getpid()); 

    return 0; 
} 

,这里是我的输出:

I'm pid 6763 
I'm pid 6765 
I'm pid 6764 
I'm pid 6766 

请忽略管道的一部分,我还没有得到那么远呢。我只是试图创建只有2个子进程,所以我期望3“我是pid ...”输出只有1为父母,我会等待和2个子进程,将通过管道进行通信。

让我知道你是否看到我的错误在哪里。

+1

'叉(2)'是既简单和UNIX API中最容易被误解的呼叫中的一个。只要看看“相关”边栏。你有没有特别的理由让你想要两个孩子之间的沟通,而不是父母与孩子之间的沟通? – dmckee

+0

对于fork()调用你为什么要检查pid == 0?我怎么知道哪一个是父母,哪个是孩子? – TwilightSparkleTheGeek

+1

@TwilightSparkleTheGeek'man fork'状态: 返回值 成功时,子进程的PID将返回到父进程中,并且子进程返回 0。失败时,-1在父代中返回, 未创建子进程,并且适当地设置errno。 – mimoralea

回答

30
pid = fork(); #1 
pidb = fork(); #2 

让我们假设父进程ID是100,第一音叉创建另一个进程101.现在,这两个100 & 101继续#1之后执行的,所以他们执行第二叉。 pid 100到达#2创建另一个进程102.pid 101到达#2创建另一个进程103.所以我们结束了4个进程。

你应该做的是这样的。

if(fork()) # parent 
    if(fork()) #parent 
    else # child2 
else #child1 
+3

这绝对有效。不过,我会建议使用switch语句。 fork函数可以返回-1,我们可以在switch语句中用case -1处理这个错误。 – sj755

+0

我以为父母是在else语句之后。为什么if语句中的父级?我很困惑。 – TwilightSparkleTheGeek

+1

因为fork在子对象上返回0,而不是父对象。在父级上,它返回刚刚创建的子进程的PID,这更有用。 – mimoralea

3

当父语句执行fork语句时,会像您期望的那样创建子进程。你可以说子进程也执行fork语句,但是返回一个0,但是,父进程返回pid。 fork语句后的所有代码都由父子两者执行。

你的情况发生了什么,第一个fork语句创建了一个子进程。所以目前有一位父母,P1和一个孩子,C1。

现在P1和C1都遇到第二个fork语句。父母创建另一个孩子(c2),就像你所期望的那样,但是即使是孩子c1也会创建一个孩子过程(c3)。所以实际上你有P1,C1,C2和C3,这就是你得到4个打印语句输出的原因。

考虑这个问题的一个好方法是使用树,每个节点代表一个进程,而根节点是最上面的父节点。

13

创建过程之后,您应该检查返回值。如果你不这样做,seconde fork()将由父进程和子进程执行,所以你有四个进程。

,如果你想创建2个进程,只是:

if (pid = fork()) { 
    if (pid = fork()) { 
     ; 
    } 
} 

您可以创建n个子流程是这样的:

for (i = 0; i < n; ++i) { 
    pid = fork(); 
    if (pid) { 
     continue; 
    } else if (pid == 0) { 
     break; 
    } else { 
     printf("fork error\n"); 
     exit(1); 
    } 
} 
0

可以检查值 如果(PID < 0 ) 进程创建不成功 这告诉子进程创建是否失败。 如果在父进程中使用getpid(),则fork返回子进程的进程ID SS ..

0

您可以在子进程中创建子进程。这样你可以拥有原始父进程的两个副本。

int main (void) { 
    pid_t pid, pid2; 
    int status; 

    pid = fork(); 

    if (pid == 0) { //child process 
     pid2 = fork(); 
     int status2; 

     if (pid2 == 0) { //child of child process 
      printf("friends!\n"); 
     } 
     else { 
      printf("my "); 
      fflush(stdout); 
      wait(&status2); 
     } 
    } 
    else { //parent process 
     printf("Hello "); 
     fflush(stdout); 
     wait(&status); 
    } 

    return 0; 
} 

此打印如下:

Hello my friends! 
相关问题