在 Windows/NTFS 中附加到文件是原子的吗?
如果我从多个进程编写一个简单的文本日志文件,它们是否会覆盖/损坏彼此的条目?
(基本上,这个问题 Is fileappendatomic-in-unix">Is fileappendatomicin-UNIX? 但对于 Windows/ NTFS。)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以在本地文件上获得原子追加。使用 FILE_APPEND_DATA 访问权限打开文件(在 WDK 中记录)。当您省略 FILE_WRITE_DATA 访问时,所有写入将忽略当前文件指针并在文件末尾完成。或者您可以使用 FILE_WRITE_DATA 访问,并在重叠结构中指定它的追加写入(Offset = FILE_WRITE_TO_END_OF_FILE 和 OffsetHigh = -1 记录在 WDK)。
追加行为在通过不同句柄的写入之间正确同步。我经常使用它来记录多个进程。我确实在每次打开时将 BOM 写入偏移量 0,并附加所有其他写入。时间戳不是问题,可以在需要时对它们进行排序。
You can get atomic append on local files. Open the file with FILE_APPEND_DATA access (Documented in WDK). When you omit FILE_WRITE_DATA access then all writes will ignore the the current file pointer and be done at the end-of file. Or you may use FILE_WRITE_DATA access and for append writes specify it in overlapped structure (Offset = FILE_WRITE_TO_END_OF_FILE and OffsetHigh = -1 Documented in WDK).
The append behavior is properly synchronized between writes via different handles. I use that regularly for logging by multiple processes. I do write BOM at every open to offset 0 and all other writes are appended. The timestamps are not a problem, they can be sorted when needed.
即使追加是原子的(我不相信它是原子的),它也可能不会给你你想要的结果。例如,假设日志包含时间戳,则期望将更新的日志附加在较旧的日志之后似乎是合理的。对于并发性,这种保证不成立 - 如果多个进程正在等待写入同一个文件,则其中任何一个进程都可能获得写锁 - 而不仅仅是最旧的进程在等待。因此,日志可能会不按顺序写入。
如果这不是理想的行为,您可以通过将所有进程的日志条目发布到共享队列(例如命名管道)来避免这种情况。然后,您将有一个进程从该队列写入日志文件。这避免了并发问题,确保日志按顺序写入,并且在文件追加不是原子性时有效,因为文件仅由一个进程直接写入。
Even if append is atomic (which I don't believe it is), it may not give you the results you want. For example, assuming a log includes a timestamp, it seems reasonable to expect more recent logs to be appended after older logs. With concurrency, this guarantee doesn't hold - if multiple processes are waiting to write to the same file, any one of them might get the write lock - not just the oldest one waiting. Thus, logs can be written out of sequence.
If this is not desirable behaviour, you can avoid it by publishing logs entries from all processes to a shared queue, such as a named pipe. You then have a single process that writes from this queue to the log file. This avoids the conccurrency issues, ensures that logs are written in order, and works when file appends are not atomic, since the file is only written to directly by one process.
从这个 MSDN 页面创建和打开文件:
和:
因此,如果您使用
CreateFile
而不是说File.Open
对文件访问没有相同级别的控制,您应该能够以这样的方式打开文件:它不会被其他进程损坏。显然,您必须向进程添加代码以应对无法独占访问日志文件的情况。
From this MSDN page on creating and opening Files:
and:
So if you use
CreateFile
rather than sayFile.Open
which doesn't have the same level of control over the file access, you should be able to open a file in such a way that it can't get corrupted by other processes.You'll obviously have to add code to your processes to cope with the case where they can't get exclusive access to the log file.
不,不是。如果您需要此文件,请参阅 事务性 NTFS Windows Vista/7。
No it isn't. If you need this there is Transactional NTFS in Windows Vista/7.