如果进程终止但系统继续运行,WriteFile()是否为原子?

时间:2014-07-30 03:23:23

标签: c windows winapi io atomic

如果我的进程随机终止,但操作系统继续正常运行,Windows是否会保证对WriteFile的单个调用是原子的(a.k.a。全有或全无)? 或者我可以获得部分/撕裂的写作吗?


注意:我特别不会就如何练习防御性编码提出建议。

严格关于Microsoft Windows 操作系统本身的行为的问题。

要100%完美清晰我们可以并且明确地 信任用户代码以表现得非常好 没有未定义的行为 或其他任何类型。假设所有流程终止都是通过明确定义的行为发生的,例如未处理的异常或对TerminateProcess的调用,内存损坏等。

另外,请特别注意,这里不需要担心C ++析构函数;这是C。

我希望将用户代码的所有次要问题都放在一边。

1 个答案:

答案 0 :(得分:3)

WriteFile肯定是原子,如果你的进程在执行时被终止,那么如果你的进程没有被杀死,它就不是原子的。

此外,"全部或全部写入" 甚至不是原子写入的正确定义。所有这些都可以编写,但与另一个进程的独立写入混合在一起。如果保证写入是原子的,那么必须有一个保证(读作:锁定),这不会发生。

除了实现适当的原子性会给普通日常用户带来很大的额外麻烦这一事实,你也可以猜测WriteFile不是原子的:

  1. API文档中没有提及。你可以打赌,这将是突出提及,因为它是一个非常大的,有区别的功能。
  2. lpNumberOfBytesWritten参数的存在。写入可能仍然失败(例如磁盘已满)但如果该函数保证是原子的,您会知道它成功或失败,并且您已经知道要写入多少字节,因此返回该数字是不必要的。
  3. TxF的存在。尽管TxF做的不仅仅是将单个写入原子化,但可以合理地假设,当正常情况下,微软不会浪费大量的时间和金钱来实现这样的野兽。无论如何,文件系统操作已经或多或少地起作用了。
  4. 我所知道的其他主流操作系统都没有提供这样的保证。 Linux确实在writev(但不在write)上提供原子性保证,因为您的写入不会与其他进程的写入混合在一起。但这与在流程终止时保证原子性完全不同。
  5. 但是,使用FILE_FLAG_NO_BUFFERING打开的句柄上的重叠写入在进程终止方面技术上原子(但不是关于故障,例如磁盘已满或在任何其他方面! )。对于实现细节而言,这样说无疑是一种诡辩,而不是操作系统给出的实际保证,但从某种观点来看,这样说肯定是正确的。
    执行无缓冲的重叠I / O操作的进程无法终止。那是因为操作系统正在将DMA传输到该过程中。地址空间。这当然意味着该过程无法终止,因为操作系统将回收物理页面。因此,当这样的I / O操作运行时,操作系统将拒绝终止进程 您可以通过触发几个大的无缓冲重叠请求(几GB)来验证这一点,并尝试在任务管理器中终止您的进程。它只会在I / O完成时被杀死(因此,在几秒钟后)。当你第一次看到它发生并且没有期待它时,这是一个很大的惊喜!