在基于Windows的操作系统中,假设有几个不同的进程可以使用fopen/fopen_s/fwrite
等来频繁地读取和/或写入文件,在这种情况下,我是否需要考虑数据竞争或操作系统可以自动处理这个,以确保文件只能在任何给定时间由一个进程打开/更新,而其余的fopen尝试将失败?那么基于linux的操作系统呢?
答案 0 :(得分:1)
在Windows中,它取决于您打开文件的方式。
在OpenFile
的情况下查看uStyle
参数的一些可能值以及CreateFile
的dwShareMode
。
请注意OpenFile
有点弃用,但最好使用CreateFile
。
答案 1 :(得分:0)
您必须注意不要同时从多个线程打开同一个文件 - 因为它完全可以多次打开文件,并且操作系统可能会或可能不会按预期执行,具体取决于您打开文件的模式 - 例如如果你创建一个新文件,肯定会创建两个不同的文件(其中一个文件在关闭时会消失,因为它被其他线程删除了,很棒,嗯?)。这些规则非常复杂,最糟糕的是,如果你不小心,你就会把输出混合到同一个文件中。" - 所以线条或甚至部分线条从两个线程混合。
即使操作系统阻止您两次打开同一个文件,您仍然需要处理" FILE *
作为NULL
"的后果。那你怎么办呢?回去再试一次,或者失败,或者?
我不确定我是否可以就如何解决这个问题提出一个很好的建议,因为你还没有很好地描述你对这些文件做了什么。我想到了一些不同的事情:
我确信还有其他几种方法可以解决问题 - 这实际上取决于你想要做什么。
答案 2 :(得分:0)
也许。如果你在谈论不同的过程(而不是 线程),适用的常规数据竞争条件 线程不适用。然而(并没有区别 在Unix和Windows之间):
任何单个write
/ WriteFile
操作都是原子操作。 (我
对Windows不是100%肯定,但我无法想象
否则。)但是,如果您使用的是iostream或更老的
FILE*
函数,你没有直接控制的时间
运作发生。通常,它们只会在发生时发生
流的缓冲区已满。你需要确保缓冲区
足够大,并在每次输出后显式刷新。 (如果
你输出了合理长度的线,比如80
最多的字符,缓冲区将是一个安全的赌注
保持完整的一条线。在这种情况下,只需使用std::endl
即可
终止iostreams中的行;对于C风格的功能,
你必须先致电setvbuf( stream, NULL, _IOLBF, 0 )
第一个输出。
流程中的每个打开文件都有自己的想法
写入文件,并自己知道文件末尾的位置。
如果您希望所有写入都转到文件末尾,则需要执行此操作
用C ++中的std::ios_base::app
或C中的“a”打开它
std::ios_base::out
/ "w"
是不够的。 (当然,
只有std::ios_base::out
或“w”,文件将是
打开时被截断。有几个不同的过程
截断文件可能会导致数据丢失。)
读取其他进程正在写入的文件时:何时
当您到达文件末尾时,流或FILE
会出错
状态,即使其他过程也不会尝试进一步阅读
正在追加数据。在C中,clearerr
应该(我认为)撤消
这个,但不清楚接下来会发生什么;在C ++中,清除
流中的错误并不一定意味着进一步读取
不会立即遇到文件结尾。同时
在最重要的情况下,最安全的选择是记住每个人之前的位置
读取,如果读取失败,请关闭文件,然后重新打开
它,寻找你所在的地方,并从那里开始阅读。
随机访问,写入文件末尾以外的其他内容
只要所有写入都是原子的(见上文);您
应始终保持一致的状态。如果你写的东西取决于
但是,你已阅读的内容以及其他流程正在进行中
类似的东西,你需要文件锁定,但不是
可在iostream / FILE*
级别使用。