使用fork后父id returns 1

Parent id returns 1 after using 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系统编程。

当子进程到达 fprintf() 时,父进程可能已经退出,导致子进程重新成为 init(PID 为 1)的父进程。

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

调用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() 返回错误指示或在 parent 进程中时,发布的代码正在退出循环。

否则,在 child 进程和 child 循环中尝试创建 childs' child.

parent 应该正在创建所有 children 并在 parent 退出之前等待 children 到 complete/exit。

waitpid() 是 parent 等待 child 的好方法)

注意:在退出 child 之前杀死 child 的 parent 会导致三种情况之一(取决于具体的 OS) child 成为僵尸或 child 成为进程 1 的 child 或 child 收到信号并退出

这里有一个如何编写代码的例子:

#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