【问题标题】:Why can "X" be the last character of output?为什么“X”可以是输出的最后一个字符?
【发布时间】:2017-12-16 20:13:53
【问题描述】:
#include <stdio.h>
#include <sys/types.h> 
#include <sys/wait.h> 
#include <sys/types.h>
#include <unistd.h>

int main() {
    if (fork() == fork()){

        fprintf(stderr, "Z");
    }
    else {
        if (waitpid((pid_t)-1,NULL,0)!=-1) {
            fprintf(stderr, "Y");

        }
        else {
            fprintf(stderr, "X");
        }
    }
}

我正在研究这个程序,我发现“ZYYX”可以作为输出。我不太明白为什么。在我的理解中,总共有四个过程,parent->parent,parent->child,child->parent,child->parent。毫无疑问,child->child 打印 Z。child->parent 在 child->child 打印 Z 之后打印 Y。而 parent->parent 应该等到 parent->child 打印 X。那么为什么 X 可能是打印为输出的最后一个字符?

【问题讨论】:

    标签: c fork pid


    【解决方案1】:

    我意识到 waitpid 会等待任何子进程,所以如果 ZY 已经打印出来,那么 Y 可以立即打印出来,因为它已经等待了“Y”。因此,X 可以作为最后一个字符打印。

    【讨论】:

    • 而 ZYYX 是唯一的模式,X 在最后一个位置。
    【解决方案2】:

    我想我以前没有在代码中看到过if (fork() == fork()) — 恭喜!我并不完全相信您的跟踪;我想查看它所做的任何打印中包含的每个进程的 PID,并且我想在每个输出的末尾添加一个换行符。另外,原始代码中至少有一个进程没有等待。

    这是一个重写,它报告执行每个打印操作的进程的 PID。一些进程以非零状态退出,主要是为了让它在输出中更有趣。该代码跟踪检测到的尸体并报告其状态。它还引入了一个循环来清理死去的孩子。原来的进程有一个没有被清理的子进程。

    #include <stdio.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    int main(void)
    {
        if (fork() == fork())
        {
            fprintf(stderr, "Z(%d)\n", (int)getpid());
            return 23;
        }
        else
        {
            int corpse;
            int status;
            if ((corpse = waitpid((pid_t)-1, &status, 0)) != -1)
                fprintf(stderr, "Y(%d) - PID %d 0x%.4X\n", (int)getpid(), corpse, status);
            else
            {
                fprintf(stderr, "X(%d)\n", (int)getpid());
                return 37;
            }
            while ((corpse = waitpid((pid_t)-1, &status, 0)) != -1)
                fprintf(stderr, "Q(%d) - PID %d 0x%.4X\n", (int)getpid(), corpse, status);
        }
        return 0;
    }
    

    示例输出:

    X(16551)
    Y(16547) - PID 16551 0x2500
    Z(16552)
    Y(16550) - PID 16552 0x1700
    Q(16547) - PID 16550 0x0000
    

    【讨论】:

      【解决方案3】:

      正如您所注意到的,将有 4 个进程,基于两个分叉,每个进程将打印一个字母:

      1st fork  2nd fork    prints                   PP
      parent    parent        Y                     /  \
      parent    child         X                   CP    PC
      child     parent        Y                    \
      child     child         Z                     CC
      

      左图显示了父/子关系——/ 是第一个分叉,\ 是第二个分叉。

      所以 CC 打印 Z,因为两个分叉都返回 0,而 PC 打印 X。另外两个都等待一个孩子退出,然后打印Y。在 CP 的 CAS 中,只有一个孩子,因此 Y 将始终在 Z 之后,但 PP 有两个孩子,因此 Y 可能在 ZY 之后或 X 之后。任何一个都是可能的。所以你可以得到任何

      XYZY   PC,PP,CC,CP
      XZYY   PC,CC,PP,CP or PC,CC,CP,PP
      ZXYY   CC,PC,PP,CP or CC,PC,CP,PP
      ZYXY   CC,CP,PC,PP
      ZYYX   CC,CP,PP,PC
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-29
        • 2017-01-26
        • 2014-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多