为什么"X"可以是输出的最后一个字符?
Why can "X" be the last character of output?
#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 可能是打印为输出的最后一个字符?
我意识到 waitpid 等待任何子进程,所以如果 ZY 已经打印出来,那么 Y 可以立即打印出来,因为它已经等待 "Y"。因此,X 可以打印为最后一个字符。
我想我以前没有在代码中看到过 if (fork() == fork())
— 恭喜!我不完全相信你的追踪;我希望看到每个进程的 PID 包含在它所做的任何打印中,并且我希望在每个输出的末尾有一个换行符。另外,原代码中至少有一个进程未等待
这是一个重写,它报告执行每个打印操作的进程的 PID。一些进程以 non-zero 状态退出,主要是为了让它在输出中更有趣一些。该代码跟踪检测到的尸体并报告其状态。它还引入了一个循环来清理死children。原始进程有一个 child,否则不会被清理。
#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
如你所见,将有 4 个进程,基于两个 fork,每个进程将打印一个字母:
1st fork 2nd fork prints PP
parent parent Y / \
parent child X CP PC
child parent Y \
child child Z CC
左边的图表显示了 parent/child 关系——/
是第一个分支,\
是第二个分支。
所以 CC 打印 Z
因为两个 fork return 0,而 PC 打印 X
。另外两个都等待 child 退出,然后打印 Y
。在CP的cas中,只有一个child,所以Y
永远在Z
之后,但是PP有两个childre,所以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
#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 可能是打印为输出的最后一个字符?
我意识到 waitpid 等待任何子进程,所以如果 ZY 已经打印出来,那么 Y 可以立即打印出来,因为它已经等待 "Y"。因此,X 可以打印为最后一个字符。
我想我以前没有在代码中看到过 if (fork() == fork())
— 恭喜!我不完全相信你的追踪;我希望看到每个进程的 PID 包含在它所做的任何打印中,并且我希望在每个输出的末尾有一个换行符。另外,原代码中至少有一个进程未等待
这是一个重写,它报告执行每个打印操作的进程的 PID。一些进程以 non-zero 状态退出,主要是为了让它在输出中更有趣一些。该代码跟踪检测到的尸体并报告其状态。它还引入了一个循环来清理死children。原始进程有一个 child,否则不会被清理。
#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
如你所见,将有 4 个进程,基于两个 fork,每个进程将打印一个字母:
1st fork 2nd fork prints PP
parent parent Y / \
parent child X CP PC
child parent Y \
child child Z CC
左边的图表显示了 parent/child 关系——/
是第一个分支,\
是第二个分支。
所以 CC 打印 Z
因为两个 fork return 0,而 PC 打印 X
。另外两个都等待 child 退出,然后打印 Y
。在CP的cas中,只有一个child,所以Y
永远在Z
之后,但是PP有两个childre,所以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