【问题标题】:Why isn't my code creating a grandchild process via fork/ C?为什么我的代码没有通过 fork/C 创建孙进程?
【发布时间】:2021-08-31 21:22:46
【问题描述】:

我以为我创建了孙子进程并尝试调用 id 以确认它与父进程/第一个子进程 id 之间的不同。有人对此有见解吗?

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

int main(void) {
  int pid;
  int pid2;
  pid = fork();
  wait(NULL);
  
  switch(pid)
  {
    case -1:
      printf("Error: Not able to fork process");
      break;
    case 0:
      printf("This appears to be the child process. The id might be %d \n", getpid());
     pid2 = fork();
     printf("Grandchild ID? %d\n", getpid());
      break;
    default:
      //printf("Are you my Dad?\n");
      printf("Are you my Dad? %d \n",getpid() );
  
      break;
  }
  //printf("Hello World\n");
  return 0;
}

【问题讨论】:

  • 请给出准确的预期结果与实际结果。对于第二个fork 调用,您没有区分父进程和子进程。
  • 你的代码可能是fork()ing 就好了。你只会得到两个Grandchild 打印输出。一个带有子 pid,一个带有孙 pid。检查this version
  • 为什么在检查fork()的返回值之前调用wait()
  • @Shawn 我已经将等待放在检查进程是否是子进程的线上,但我认为我做错了,因为输出不一致。我尝试将等待移到现在的位置,并且得到一致的输出。但是,在我看来,我的第二个 fork 并没有从第一个子进程创建子进程。
  • @kaylum 我认为我的代码会打印以下内容,除了显示孙进程的唯一 ID,但它看起来与子进程相同。我This appears to be the child process. The id might be 41 Grandchild ID? 41 Are you my Dad? 40

标签: c fork


【解决方案1】:

了解正在发生的事情的最佳方法是更全面地检测代码,打印更多信息。这是您的代码的改编版:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>

int main(void)
{
    printf("%5d: initial process (PPID %d)\n", getpid(), getppid());

    int pid = fork();

    printf("%5d: after fork (PPID %d)\n", getpid(), getppid());

    int status;
    int corpse = wait(&status);
    if (corpse > 0)
        printf("%5d: child %d died with status 0x%.4X\n", getpid(), corpse, status);
    else
        fprintf(stderr, "%5d: wait failed (%d: %s)\n", getpid(), errno, strerror(errno));

    switch (pid)
    {
    case -1:
        fprintf(stderr, "%5d: Error: Not able to fork process (%d: %s)\n",
                getpid(), errno, strerror(errno));
        break;
    case 0:
        printf("%5d: Child process\n", getpid());
        int pid2 = fork();
        if (pid2 < 0)
            fprintf(stderr, "%5d: failed to fork grandchild (PPID %d)\n", getpid(), getppid());
        else if (pid2 > 0)
            printf("%5d: grandchild has PID %d\n", getpid(), pid2);
        else
            printf("%5d: I am the grandchild (PPID %d)\n", getpid(), getppid());
        break;
    default:
        // printf("Are you my Dad?\n");
        printf("%5d: child PID %d\n", getpid(), pid);
        break;
    }
    printf("%5d: Exiting (PPID %d)\n", getpid(), getppid());
    return 0;
}

注意消息是如何使用当前 PID 统一前缀的,通过每次调用getpid() 获得。还要注意,每次系统调用后都会打印该信息。

一个示例运行(源代码gk89.c,程序gk89):

$ ./gk89
54711: initial process (PPID 2943)
54711: after fork (PPID 2943)
54712: after fork (PPID 54711)
54712: wait failed (10: No child processes)
54712: Child process
54712: grandchild has PID 54713
54712: Exiting (PPID 54711)
54713: I am the grandchild (PPID 54712)
54711: child 54712 died with status 0x0000
54711: child PID 54712
54711: Exiting (PPID 2943)
54713: Exiting (PPID 1)
$

请注意,孙子被创建 (PID 54713),最初的父 PID 为 54712,但在它退出时,它的父已经死了,所以它在退出时将其 PPID 报告为 1。它已被系统进程继承,通常称为init,主要等待孤立进程(它自动继承)死亡。

显示的顺序取决于系统调度进程的突发奇想。碰巧孙子的退出消息是在 shell 提示符 ($) 之前打印的,但这不能保证。 OTOH,由于wait() 调用,在子进程退出之前,初始进程不会退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-02
    • 2023-02-19
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多