为什么在我的centos中打印三遍'hello'?
why print 'hello' three times in my centos?
#include "csapp.h"
int main()
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
/*
* .------------------------
* |
* |
* |
* .-----------.------------------------
* |
* |
* | .------------------------
* | |
* | |
* | |
* .-----------.------------------------
* fork fork
* i=0 i=1
*/
在过程图片中,代码似乎会打印 "hello" 四次。
为什么我的centos打印三遍'hello'?
可能分叉失败或 printf
之间存在冲突。在 ideone 上它正确打印了 4 次。
除非你的 csapp.h
header 中有什么奇怪的东西,否则你应该打印出四行,因为在循环的第一次迭代之后(增量之前的 i == 0
), fork()
创建两个进程,在第二次迭代(增量之前的 i == 1
),这两个进程中的每一个都执行 fork()
以创建另外两个进程。
当此代码在 macOS 10.14.6 上为 运行 时,我得到 4 行 hello
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
输出:
hello
hello
hello
hello
不过,我对它的检测远不止问题中显示的最少代码 — 像这样:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: i = %d, PID = %d, PPID = %d, fork = %d\n",
i, (int)getpid(), (int)getppid(), pid);
fflush(stdout);
}
printf("Hello: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
return(0);
}
注意大量使用 fflush()
以避免 printf()
anomaly after fork()
。
我从中得到的示例输出是:
P0: PID = 5039, PPID = 916
PF: i = 0, PID = 5039, PPID = 916, fork = 5042
PF: i = 1, PID = 5039, PPID = 916, fork = 5043
Hello: PID = 5039, PPID = 916
PF: i = 0, PID = 5042, PPID = 5039, fork = 0
PF: i = 1, PID = 5043, PPID = 1, fork = 0
Hello: PID = 5043, PPID = 1
PF: i = 1, PID = 5042, PPID = 1, fork = 5044
Hello: PID = 5042, PPID = 1
PF: i = 1, PID = 5044, PPID = 5042, fork = 0
Hello: PID = 5044, PPID = 5042
请注意,其中两个进程报告 PPID = 1
,因为 parent 进程 (5039) 已经退出。添加一个循环等待children死亡并报告它们的退出状态将是feasible/sensible。
#include <sys/wait.h>
…
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %d, PPID = %d, child %d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
你在 CentOS 上得到了什么?
我运行在终端window中从命令行运行程序。如果您从 IDE 之类的 运行 宁此,您可能会丢失孤立进程的输出。添加 wait()
循环将阻止第一个进程退出,直到它的 children 的所有(两个)都退出,从而导致 4 "Hello" 行的有序显示。我修改了输出格式,以便更容易阅读输出。
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: PID = %5d, PPID = %5d, i = %d, fork = %5d\n",
(int)getpid(), (int)getppid(), i, pid);
fflush(stdout);
}
printf("hello\n");
printf("HO: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %5d, PPID = %5d, child %5d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
printf("EX: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
return(0);
}
示例输出(无孤立进程):
P0: PID = 5245, PPID = 916
PF: PID = 5245, PPID = 916, i = 0, fork = 5248
PF: PID = 5248, PPID = 5245, i = 0, fork = 0
PF: PID = 5245, PPID = 916, i = 1, fork = 5249
hello
HO: PID = 5245, PPID = 916
PF: PID = 5248, PPID = 5245, i = 1, fork = 5250
PF: PID = 5249, PPID = 5245, i = 1, fork = 0
hello
HO: PID = 5248, PPID = 5245
hello
HO: PID = 5249, PPID = 5245
EX: PID = 5249, PPID = 5245
PF: PID = 5250, PPID = 5248, i = 1, fork = 0
hello
HO: PID = 5250, PPID = 5248
EX: PID = 5250, PPID = 5248
WT: PID = 5245, PPID = 916, child 5249 exited 0x0000
WT: PID = 5248, PPID = 5245, child 5250 exited 0x0000
EX: PID = 5248, PPID = 5245
WT: PID = 5245, PPID = 916, child 5248 exited 0x0000
EX: PID = 5245, PPID = 916
#include "csapp.h"
int main()
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
/*
* .------------------------
* |
* |
* |
* .-----------.------------------------
* |
* |
* | .------------------------
* | |
* | |
* | |
* .-----------.------------------------
* fork fork
* i=0 i=1
*/
在过程图片中,代码似乎会打印 "hello" 四次。 为什么我的centos打印三遍'hello'?
可能分叉失败或 printf
之间存在冲突。在 ideone 上它正确打印了 4 次。
除非你的 csapp.h
header 中有什么奇怪的东西,否则你应该打印出四行,因为在循环的第一次迭代之后(增量之前的 i == 0
), fork()
创建两个进程,在第二次迭代(增量之前的 i == 1
),这两个进程中的每一个都执行 fork()
以创建另外两个进程。
当此代码在 macOS 10.14.6 上为 运行 时,我得到 4 行 hello
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i;
for (i = 0; i < 2; i++)
fork();
printf("hello\n");
exit(0);
}
输出:
hello
hello
hello
hello
不过,我对它的检测远不止问题中显示的最少代码 — 像这样:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: i = %d, PID = %d, PPID = %d, fork = %d\n",
i, (int)getpid(), (int)getppid(), pid);
fflush(stdout);
}
printf("Hello: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
return(0);
}
注意大量使用 fflush()
以避免 printf()
anomaly after fork()
。
我从中得到的示例输出是:
P0: PID = 5039, PPID = 916
PF: i = 0, PID = 5039, PPID = 916, fork = 5042
PF: i = 1, PID = 5039, PPID = 916, fork = 5043
Hello: PID = 5039, PPID = 916
PF: i = 0, PID = 5042, PPID = 5039, fork = 0
PF: i = 1, PID = 5043, PPID = 1, fork = 0
Hello: PID = 5043, PPID = 1
PF: i = 1, PID = 5042, PPID = 1, fork = 5044
Hello: PID = 5042, PPID = 1
PF: i = 1, PID = 5044, PPID = 5042, fork = 0
Hello: PID = 5044, PPID = 5042
请注意,其中两个进程报告 PPID = 1
,因为 parent 进程 (5039) 已经退出。添加一个循环等待children死亡并报告它们的退出状态将是feasible/sensible。
#include <sys/wait.h>
…
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %d, PPID = %d, child %d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
你在 CentOS 上得到了什么?
我运行在终端window中从命令行运行程序。如果您从 IDE 之类的 运行 宁此,您可能会丢失孤立进程的输出。添加 wait()
循环将阻止第一个进程退出,直到它的 children 的所有(两个)都退出,从而导致 4 "Hello" 行的有序显示。我修改了输出格式,以便更容易阅读输出。
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int i;
printf("P0: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
for (i = 0; i < 2; i++)
{
int pid = fork();
printf("PF: PID = %5d, PPID = %5d, i = %d, fork = %5d\n",
(int)getpid(), (int)getppid(), i, pid);
fflush(stdout);
}
printf("hello\n");
printf("HO: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
fflush(stdout);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("WT: PID = %5d, PPID = %5d, child %5d exited 0x%.4X\n",
(int)getpid(), (int)getppid(), corpse, status);
fflush(stdout);
}
printf("EX: PID = %5d, PPID = %5d\n", (int)getpid(), (int)getppid());
return(0);
}
示例输出(无孤立进程):
P0: PID = 5245, PPID = 916
PF: PID = 5245, PPID = 916, i = 0, fork = 5248
PF: PID = 5248, PPID = 5245, i = 0, fork = 0
PF: PID = 5245, PPID = 916, i = 1, fork = 5249
hello
HO: PID = 5245, PPID = 916
PF: PID = 5248, PPID = 5245, i = 1, fork = 5250
PF: PID = 5249, PPID = 5245, i = 1, fork = 0
hello
HO: PID = 5248, PPID = 5245
hello
HO: PID = 5249, PPID = 5245
EX: PID = 5249, PPID = 5245
PF: PID = 5250, PPID = 5248, i = 1, fork = 0
hello
HO: PID = 5250, PPID = 5248
EX: PID = 5250, PPID = 5248
WT: PID = 5245, PPID = 916, child 5249 exited 0x0000
WT: PID = 5248, PPID = 5245, child 5250 exited 0x0000
EX: PID = 5248, PPID = 5245
WT: PID = 5245, PPID = 916, child 5248 exited 0x0000
EX: PID = 5245, PPID = 916