多处理和文件操作?

时间:2013-02-14 11:57:37

标签: c++ c windows multiprocessing

在基于Windows的操作系统中,假设有几个不同的进程可以使用fopen/fopen_s/fwrite等来频繁地读取和/或写入文件,在这种情况下,我是否需要考虑数据竞争或操作系统可以自动处理这个,以确保文件只能在任何给定时间由一个进程打开/更新,而其余的fopen尝试将失败?那么基于linux的操作系统呢?

3 个答案:

答案 0 :(得分:1)

在Windows中,它取决于您打开文件的方式。

OpenFile的情况下查看uStyle参数的一些可能值以及CreateFiledwShareMode

请注意OpenFile有点弃用,但最好使用CreateFile

答案 1 :(得分:0)

您必须注意不要同时从多个线程打开同一个文件 - 因为它完全可以多次打开文件,并且操作系统可能会或可能不会按预期执行,具体取决于您打开文件的模式 - 例如如果你创建一个新文件,肯定会创建两个不同的文件(其中一个文件在关闭时会消失,因为它被其他线程删除了,很棒,嗯?)。这些规则非常复杂,最糟糕的是,如果你不小心,你就会把输出混合到同一个文件中。" - 所以线条或甚至部分线条从两个线程混合。

即使操作系统阻止您两次打开同一个文件,您仍然需要处理" FILE *作为NULL"的后果。那你怎么办呢?回去再试一次,或者失败,或者?

我不确定我是否可以就如何解决这个问题提出一个很好的建议,因为你还没有很好地描述你对这些文件做了什么。我想到了一些不同的事情:

  1. 保持"注册"文件名,以及必须保持以便能够打开文件的每个文件的互斥锁。
  2. 使用单个"文件线程"读取/写入文件数据,然后排队"我想将这些东西写入文件aa.txt",并让工作人员随时写入。
  3. 使用较低级别的文件系统调用,并使用" exclusive"访问文件,某种"退避"碰撞时的行为。
  4. 我确信还有其他几种方法可以解决问题 - 这实际上取决于你想要做什么。

答案 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*级别使用。