如果我的进程随机终止,但操作系统继续正常运行,Windows是否会保证对WriteFile
的单个调用是原子的(a.k.a。全有或全无)?
或者我可以获得部分/撕裂的写作吗?
严格关于Microsoft Windows 操作系统本身的行为的问题。
要100%完美清晰,我们可以并且明确地 信任用户代码以表现得非常好。 没有未定义的行为 或其他任何类型。假设所有流程终止都是通过明确定义的行为发生的,例如未处理的异常或对TerminateProcess
的调用,不内存损坏等。
另外,请特别注意,这里不需要担心C ++析构函数;这是C。
我希望将用户代码的所有次要问题都放在一边。
答案 0 :(得分:3)
WriteFile
肯定是不原子,如果你的进程在执行时被终止,那么如果你的进程没有被杀死,它就不是原子的。
此外,"全部或全部写入" 甚至不是原子写入的正确定义。所有这些都可以编写,但与另一个进程的独立写入混合在一起。如果保证写入是原子的,那么必须有一个保证(读作:锁定),这不会发生。
除了实现适当的原子性会给普通日常用户带来很大的额外麻烦这一事实,你也可以猜测WriteFile
不是原子的:
lpNumberOfBytesWritten
参数的存在。写入可能仍然失败(例如磁盘已满)但如果该函数保证是原子的,您会知道它成功或失败,并且您已经知道要写入多少字节,因此返回该数字是不必要的。 writev
(但不在write
)上提供种原子性保证,因为您的写入不会与其他进程的写入混合在一起。但这与在流程终止时保证原子性完全不同。但是,使用FILE_FLAG_NO_BUFFERING
打开的句柄上的重叠写入在进程终止方面技术上原子(但不是关于故障,例如磁盘已满或在任何其他方面! )。对于实现细节而言,这样说无疑是一种诡辩,而不是操作系统给出的实际保证,但从某种观点来看,这样说肯定是正确的。
执行无缓冲的重叠I / O操作的进程无法终止。那是因为操作系统正在将DMA传输到该过程中。地址空间。这当然意味着该过程无法终止,因为操作系统将回收物理页面。因此,当这样的I / O操作运行时,操作系统将拒绝终止进程
您可以通过触发几个大的无缓冲重叠请求(几GB)来验证这一点,并尝试在任务管理器中终止您的进程。它只会在I / O完成时被杀死(因此,在几秒钟后)。当你第一次看到它发生并且没有期待它时,这是一个很大的惊喜!