清理后,您的代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i = 0, tube1[2], tube2[2], pid;
if (pipe(tube1) == -1 || pipe(tube2) == -1)
{
perror("pipe");
exit(0);
}
pid = fork();
while (i < 100)
{
if (pid == 0)
{
printf("fils ");
do
{
i = i + 2;
printf("%d ", i);
} while (i % 5 != 0);
putchar('\n');
write(tube1[1], &i, sizeof(int));
read(tube2[0], &i, sizeof(int));
}
else
{
printf("pere ");
read(tube1[0], &i, sizeof(int));
do
{
i = i + 3;
printf("%d ", i);
} while (i % 5 != 0);
putchar('\n');
write(tube2[1], &i, sizeof(int));
}
}
close(tube1[1]);
close(tube1[0]);
close(tube2[1]);
close(tube2[0]);
}
一个变化是进程在写入一系列数字后输出换行符,而不是等到读/写操作之后。
循环是复杂的,因为您有一个外部while (i < 100) 循环,然后每个进程都有一个递增i 的内部循环。然后,更复杂的事情是,孩子将其当前值i 发送给父母,父母在其循环中使用它,然后父母将自己的i 值发送给孩子,孩子恢复它的使用i 的新值;冲洗并重复。输出是:
fils 2 4 6 8 10
pere 13 16 19 22 25
fils 27 29 31 33 35
pere 38 41 44 47 50
fils 52 54 56 58 60
pere 63 66 69 72 75
fils 77 79 81 83 85
pere 88 91 94 97 100
可以看到孩子生成的值是10;然后父母将 3 添加到它从孩子收到的值(因此为 13)并迭代;然后它将 25 发送给孩子,孩子加 2(因此为 27)并迭代;等等。
要获得您寻求的结果,您需要将同步中使用的值与控制循环的值分离。您还面临一个问题,因为子进程会尝试比父进程运行更长的时间,但幸运的是,它会收到一个 SIGPIPE 信号,并且当它尝试写入父进程已关闭的管道时会死掉——或者更确切地说,如果它已经关闭了它不使用的管道末端。在生成换行符之后刷新标准输出也是一个好主意。这些变化导致:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int i = 0, tube1[2], tube2[2], pid;
if (pipe(tube1) == -1 || pipe(tube2) == -1)
{
perror("pipe");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if (pid == 0)
{
close(tube1[0]);
close(tube2[1]);
}
else
{
close(tube1[1]);
close(tube2[0]);
}
while (i < 100)
{
if (pid == 0)
{
printf("fils ");
do
{
i = i + 2;
printf("%d ", i);
} while (i % 5 != 0);
putchar('\n');
fflush(stdout);
int j = 0;
write(tube1[1], &j, sizeof(int));
read(tube2[0], &j, sizeof(int));
}
else
{
int j = 0;
read(tube1[0], &j, sizeof(int));
printf("pere ");
do
{
i = i + 3;
printf("%d ", i);
} while (i % 5 != 0);
putchar('\n');
fflush(stdout);
write(tube2[1], &j, sizeof(int));
}
}
close(tube1[1]);
close(tube1[0]);
close(tube2[1]);
close(tube2[0]);
}
然后输出是:
fils 2 4 6 8 10
pere 3 6 9 12 15
fils 12 14 16 18 20
pere 18 21 24 27 30
fils 22 24 26 28 30
pere 33 36 39 42 45
fils 32 34 36 38 40
pere 48 51 54 57 60
fils 42 44 46 48 50
pere 63 66 69 72 75
fils 52 54 56 58 60
pere 78 81 84 87 90
fils 62 64 66 68 70
pere 93 96 99 102 105
fils 72 74 76 78 80
请注意,孩子没有达到 100,因为父母退出,而父母超过 100,因为检查发生在外循环,而不是内循环。
我保留了你的循环组织,但如果它是我自己的代码,它将有两个函数——be_childish() 和be_parental()——它们将在 fork 之后调用,并且每个函数都将运行自己的相关循环。管道将被传递给函数,它们会“更好地”清理。请注意,程序末尾的 4 个 close() 调用中有 2 个将失败,因为这些管道描述符之前已关闭。区分哪些是繁琐的;最好把代码拆分成函数。