我不清楚你是如何在输出中得到重复的行的。我的最佳猜测是您遇到了printf() anomaly after fork() 中详述的问题。
我为您的代码创建了一个经过轻微修改的变体。我修改了您的打印代码以打印子 PID(n 的值)以及父进程的信息,并修改了格式,使 PID 始终占用 5 个空格进行对齐。
我添加了代码以接受 -i 3 的迭代次数(默认为 3 次),并接受 -w 以让进程在退出之前等待所有子进程死亡。
代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
int i;
int n;
int waitmode = 0;
int iterations = 3;
int opt;
while ((opt = getopt(argc, argv, "i:w")) != -1)
{
switch (opt)
{
case 'i':
iterations = atoi(optarg);
break;
case 'w':
waitmode = 1;
break;
default:
exit(1);
}
}
if (argc != optind)
{
fprintf(stderr, "Usage: forkloop [-i iterations] [-w]\n");
exit(1);
}
for (i = 0; i < iterations; i++)
{
n = fork();
if (n < 0)
{
perror("fork");
exit(1);
}
// printf("pid = %5d, i = %d\n", getpid(), i);
printf("ppid = %5d, pid = %5d, i = %d (n = %5d)\n", getppid(), getpid(), i, n);
}
if (waitmode)
{
int status;
int corpse;
while ((corpse = wait(&status)) != -1)
{
printf("ppid = %5d, pid = %5d, corpse = %5d, status = 0x%.4X\n",
getppid(), getpid(), corpse, status);
}
}
return 0;
}
样本运行
无论好坏,我将程序称为pff19 而不是forkloop。
我正在使用 GCC 6.1.0 在 Mac OS X 10.11.5 上进行测试。该机器具有 Intel Core i7 芯片,因此具有多个内核。当没有等待时,这很重要; PPID 1 表示进程的父进程在孩子报告之前已经死亡。您可以在最后一组输出中看到 PID 15908 首先报告 PPID 15907 然后 PPID 1。
当程序的输出通过cat 进行管道传输时,输出是完全缓冲的,因此子进程在其输出缓冲区中具有其父进程已经打印但尚未刷新的数据 - 这就是'@987654331 @fork()'行为之后的异常。
$ pff19 -i 3 | cat
ppid = 85956, pid = 15878, i = 0 (n = 15880)
ppid = 85956, pid = 15878, i = 1 (n = 15881)
ppid = 85956, pid = 15878, i = 2 (n = 15882)
ppid = 85956, pid = 15878, i = 0 (n = 15880)
ppid = 85956, pid = 15878, i = 1 (n = 15881)
ppid = 1, pid = 15882, i = 2 (n = 0)
ppid = 85956, pid = 15878, i = 0 (n = 15880)
ppid = 15878, pid = 15881, i = 1 (n = 0)
ppid = 1, pid = 15881, i = 2 (n = 15884)
ppid = 15878, pid = 15880, i = 0 (n = 0)
ppid = 1, pid = 15880, i = 1 (n = 15883)
ppid = 1, pid = 15880, i = 2 (n = 15885)
ppid = 85956, pid = 15878, i = 0 (n = 15880)
ppid = 15878, pid = 15881, i = 1 (n = 0)
ppid = 1, pid = 15884, i = 2 (n = 0)
ppid = 15878, pid = 15880, i = 0 (n = 0)
ppid = 1, pid = 15880, i = 1 (n = 15883)
ppid = 1, pid = 15885, i = 2 (n = 0)
ppid = 15878, pid = 15880, i = 0 (n = 0)
ppid = 15880, pid = 15883, i = 1 (n = 0)
ppid = 1, pid = 15883, i = 2 (n = 15886)
ppid = 15878, pid = 15880, i = 0 (n = 0)
ppid = 15880, pid = 15883, i = 1 (n = 0)
ppid = 15883, pid = 15886, i = 2 (n = 0)
$ pff19 -w -i 3 | cat
ppid = 85956, pid = 15888, i = 0 (n = 15890)
ppid = 85956, pid = 15888, i = 1 (n = 15891)
ppid = 15888, pid = 15892, i = 2 (n = 0)
ppid = 85956, pid = 15888, i = 0 (n = 15890)
ppid = 15888, pid = 15891, i = 1 (n = 0)
ppid = 15891, pid = 15895, i = 2 (n = 0)
ppid = 15888, pid = 15890, i = 0 (n = 0)
ppid = 15888, pid = 15890, i = 1 (n = 15893)
ppid = 15890, pid = 15894, i = 2 (n = 0)
ppid = 15888, pid = 15890, i = 0 (n = 0)
ppid = 15890, pid = 15893, i = 1 (n = 0)
ppid = 15893, pid = 15896, i = 2 (n = 0)
ppid = 85956, pid = 15888, i = 0 (n = 15890)
ppid = 15888, pid = 15891, i = 1 (n = 0)
ppid = 15888, pid = 15891, i = 2 (n = 15895)
ppid = 15888, pid = 15891, corpse = 15895, status = 0x0000
ppid = 15888, pid = 15890, i = 0 (n = 0)
ppid = 15890, pid = 15893, i = 1 (n = 0)
ppid = 15890, pid = 15893, i = 2 (n = 15896)
ppid = 15890, pid = 15893, corpse = 15896, status = 0x0000
ppid = 15888, pid = 15890, i = 0 (n = 0)
ppid = 15888, pid = 15890, i = 1 (n = 15893)
ppid = 15888, pid = 15890, i = 2 (n = 15894)
ppid = 15888, pid = 15890, corpse = 15894, status = 0x0000
ppid = 15888, pid = 15890, corpse = 15893, status = 0x0000
ppid = 85956, pid = 15888, i = 0 (n = 15890)
ppid = 85956, pid = 15888, i = 1 (n = 15891)
ppid = 85956, pid = 15888, i = 2 (n = 15892)
ppid = 85956, pid = 15888, corpse = 15892, status = 0x0000
ppid = 85956, pid = 15888, corpse = 15891, status = 0x0000
ppid = 85956, pid = 15888, corpse = 15890, status = 0x0000
$ pff19 -w -i 3
ppid = 85956, pid = 15898, i = 0 (n = 15899)
ppid = 85956, pid = 15898, i = 1 (n = 15900)
ppid = 15898, pid = 15899, i = 0 (n = 0)
ppid = 85956, pid = 15898, i = 2 (n = 15901)
ppid = 15898, pid = 15899, i = 1 (n = 15902)
ppid = 15898, pid = 15900, i = 1 (n = 0)
ppid = 15898, pid = 15901, i = 2 (n = 0)
ppid = 15898, pid = 15899, i = 2 (n = 15903)
ppid = 15898, pid = 15900, i = 2 (n = 15904)
ppid = 15899, pid = 15902, i = 1 (n = 0)
ppid = 85956, pid = 15898, corpse = 15901, status = 0x0000
ppid = 15899, pid = 15902, i = 2 (n = 15905)
ppid = 15899, pid = 15903, i = 2 (n = 0)
ppid = 15900, pid = 15904, i = 2 (n = 0)
ppid = 15898, pid = 15899, corpse = 15903, status = 0x0000
ppid = 15902, pid = 15905, i = 2 (n = 0)
ppid = 15898, pid = 15900, corpse = 15904, status = 0x0000
ppid = 15899, pid = 15902, corpse = 15905, status = 0x0000
ppid = 85956, pid = 15898, corpse = 15900, status = 0x0000
ppid = 15898, pid = 15899, corpse = 15902, status = 0x0000
ppid = 85956, pid = 15898, corpse = 15899, status = 0x0000
$ pff19 -i 3
ppid = 85956, pid = 15907, i = 0 (n = 15908)
ppid = 85956, pid = 15907, i = 1 (n = 15909)
ppid = 15907, pid = 15908, i = 0 (n = 0)
ppid = 85956, pid = 15907, i = 2 (n = 15910)
ppid = 15907, pid = 15908, i = 1 (n = 15911)
ppid = 15907, pid = 15909, i = 1 (n = 0)
ppid = 15907, pid = 15910, i = 2 (n = 0)
ppid = 15907, pid = 15909, i = 2 (n = 15913)
ppid = 1, pid = 15908, i = 2 (n = 15912)
ppid = 15908, pid = 15911, i = 1 (n = 0)
ppid = 1, pid = 15913, i = 2 (n = 0)
ppid = 1, pid = 15911, i = 2 (n = 15914)
ppid = 1, pid = 15912, i = 2 (n = 0)
ppid = 1, pid = 15914, i = 2 (n = 0)
$