使用fork后,父ID返回1

时间:2016-02-01 03:53:32

标签: c unix operating-system fork

我对以下代码的输出感到困惑。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
   pid_t childpid = 0;
   int i, n;
   if (argc != 2){   /* check for valid number of command-line arguments */
       fprintf(stderr, "Usage: %s processes\n", argv[0]);
       return 1;
   }
   n = atoi(argv[1]);
   for (i = 1; i < n; i++)
   if ((childpid = fork()))
       break;
   fprintf(stderr,"i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
       i, (long)getpid(), (long)getppid(), (long)childpid);
   return 0; 
}
使用命令参数n = 3运行后输出

i:1  process ID:3662  parent ID:2658  child ID:3663
i:2  process ID:3663  parent ID:1  child ID:3664
i:3  process ID:3664  parent ID:1  child ID:0

我想知道为什么父ID始终为1,并且在我将最后一行代码更改为之后 printf而不是fprintf,父ID偶尔只包含1。这是 教科书中的一个例子 - Unix系统编程。

2 个答案:

答案 0 :(得分:2)

当孩子们到达fprintf()时,父进程可能已经退出,导致子进程被重新分配给init(具有PID 1)。

sleep(1)之前添加return 0可能会解决此问题。

答案 1 :(得分:0)

调用fork()时,有3种返回值。

-1 when the `fork()` failed to create a child process
0 when the current process is the child
>0 when the current process is the parent.

fork()返回错误指示或在父进程中时,已发布的代码将退出循环。

另一方面,在孩子的过程中,孩子绕着圈子试图创造一个孩子。子。

父母应该创建所有孩子并等待孩子在父退出之前完成/退出。

waitpid()是父母等待孩子的好方法)

注意:在退出孩子之前杀死孩子的父母可能导致三种情况中的任何一种(取决于特定的OS)孩子变成僵尸或孩子成为过程1的孩子或孩子得到信号并退出

这是一个如何编写代码的示例:

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

int main (int argc, char *argv[])
{
    int i, n;

    if (argc != 2)
    {   /* check for valid number of command-line arguments */
        fprintf(stderr, "Usage: %s <Number of child processes to create>\n", argv[0]);
        exit( EXIT_FAILURE );
    }

    // implied else, correct number of arguments

    n = atoi(argv[1]);

    pid_t childpid[n];

    for (i = 0; i < n; i++)
    {
        switch( childpid[i] = fork() )
        {
           case -1:
                // handle fork failure
                perror( "fork failed" );
                exit( EXIT_FAILURE );
                break;

            case 0:
                // handle child
                fprintf(stderr,
                        "i:%d  CHILD process ID:%ld  PARENT process ID:%ld\n",
                         i,
                         (long)getpid(),
                         (long)getppid());
                exit( EXIT_SUCCESS );
                break;

            default:
                // handle parent
                fprintf(stderr,
                        "i:%d  PARENT process ID:%ld  CHILD process ID:%ld\n",
                         i,
                         (long)getpid(),
                         (long)childpid[i]);
                break;
        } // end switch
    } // end for

    for( i=0; i<n; i++ )
    {
        waitpid( childpid[i], NULL, 0 );
    }

   return 0;
} // end function: main

示例输出是:当命令行参数为3

i:0  PARENT process ID:918  CHILD process ID:919
i:1  PARENT process ID:918  CHILD process ID:920
i:0  CHILD process ID:919  PARENT process ID:918
i:1  CHILD process ID:920  PARENT process ID:918
i:2  PARENT process ID:918  CHILD process ID:921
i:2  CHILD process ID:921  PARENT process ID:918