#include <fcntl.h>
#include <stdlib.h>
int fdrd,fdwt;
char c;
void rdwrt();
main(int argc,char *argv[])
{
if(argc!=3)
exit(1);
if((fdrd=open(argv[1],O_RDONLY))==-1)
exit(1);
if((fdwt=creat(argv[2],0666))==01)
exit(1);
fork();
rdwrt();
exit(0);
}
void rdwrt()
{
for(;;)
{
if(read(fdrd,&c,1)!=1)
return;
write(fdwt,&c,1);
}
}
此程序分叉子进程,然后父进程和子进程尝试读取相同的输入文件并写入相同的输出文件。
像这样执行此程序:
[root@localhost]./a.out input output
输入文件的内容为:
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
我认为输出文件应该与输入文件具有相同数量的字符,但根据这两个过程的竞争,字符顺序可能不一样。
事实证明输出文件是:
abcdefghijklmnonqbcdefghijklwxyczdefjklpqrstuvwxyz
abcefgklmvwxefgklmnopqrstuvw
qrstuyz
abcdhijxyz
实际上,这些两个文件的字符数不同:
[root@localhost]wc -m input output
162 input
98 output
现在我想知道为什么?
答案 0 :(得分:1)
输出文件的内容很难预测,因为您的程序包含race condition.具体而言,它取决于进程安排。
请求更新:
这个问题实际上比第一眼看上去更有趣。
我要做一些预测(测试成功......)
在类Unix系统上 1 ...然后,是,字符数总是相同但订单很难预测。
你标记了你的问题 linux unix ,在那些系统中,所有 1 正确实现了fork模型,两个孩子都会分享fdrd
的两个(分叉)实例的单个文件位置,它们将为fdwr
的两个实例共享第二个文件位置。
如果你可以减慢时间并观看程序运行,那么在任何时候都会有你知道的事情和你不知道的事情。
您不知道哪个孩子会赢得下一次阅读的比赛,但您做知道获胜者将阅读哪个角色,因为他们总是在同一档位。在获胜者获得下一个角色后,您仍然不知道谁会阅读下一个角色,因为比赛仍在进行。
事实上,同一个进程可能会再次赢得比赛,而且,因为调度程序可能不希望在非常短的时间内运行它。
在任何时候你都知道下一个字符将被写在EOF上,因为共享写入位置。
现在,您可能会问,如果两个进程始终处于相同的输入和输出文件位置,文件将如何被破解?
嗯,有不止一场比赛,一场比赛,另一场比赛。 (或者一种,有点复杂的种族。)一个孩子可能已经读过它的角色,但是当它被时间切片时没有写出来。所以现在它开始失去比赛到写声明,然后可能会发生几次读/写迭代。所以一个角色可以挂在一个孩子身上。
最后,在与其他操作系统运行的仅仅API兼容的C环境中,任何事情都可能发生。 OP的系统似乎是其中之一,或者测试可能存在缺陷。我的OSX系统表现如预期。
<小时/> 1。 “真正的”UNIX,* BSD,OSX或Linux。