#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
现在我想知道为什么?
最佳答案
输出文件的内容将很难预测,因为您的程序包含 race condition.具体取决于进程调度。
请求的更新:
这个问题其实比第一眼看上去更有趣。
我要做出一些预测(测试成功...)
在类 Unix 系统上1 ...那么,是,字符数将始终相同,但顺序将难以预测。
您将您的问题标记为 linux unix,并且在这些系统中,所有这些1 都正确地实现了 fork 模型,两个 child 将共享fdrd
的两个(分支)实例的单个文件位置,并且它们将为 fdwr
的两个实例共享第二个文件位置。
如果你能放慢时间并观察程序运行,那么在任何时候都有你知道的事情和你不知道的事情。
您不知道哪个 child 会赢得下一次阅读的比赛,但您确实知道获胜者将阅读哪个字符,因为他们总是在相同的文件位置。在获胜者获得下一个字符后,您仍然不知道谁会阅读下一个字符,因为比赛仍在继续。
事实上,同一个进程有可能一次又一次地赢得比赛,因为调度程序可能不想在非常短的时间片内运行它。
在任何时候您也知道下一个字符将在 EOF 处写入,因为再次共享写入位置。
现在,您可能会问,那么,如果两个进程始终位于相同的输入和输出文件位置,文件是如何被破解的?
好吧,有不止一场比赛,一场是阅读,另一场是写作。 (或者一个,有点复杂的种族。)一个 child 可能已经读过它的字符,但当它被时间分割时还没有写出来。所以现在它开始输给写入语句,然后可能输给几次读/写迭代。所以一个角色可能会卡在一个 child 身上。
最后,在其他操作系统上运行的仅与 API 兼容的 C 环境中,任何事情都可能发生。 OP 的系统似乎是其中之一,或者测试可能存在缺陷。我的 OSX 系统表现如预期。
<补充>1。 “真正的”UNIX、*BSD、OSX 或 Linux。
关于linux - 当父进程和子进程读取同一个文件并写入另一个同一个文件时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15927578/