如果我从多个进程编写一个简单的文本日志文件,它们是否会覆盖/损坏彼此的条目?
(基本上,这个问题Is file append atomic in UNIX?但是对于Windows / NTFS。)
答案 0 :(得分:12)
您可以在本地文件上获得原子追加。使用FILE_APPEND_DATA访问权限打开文件(在WDK中记录)。省略FILE_WRITE_DATA访问时,所有写入都将忽略当前文件指针,并在文件末尾完成。或者您可以使用FILE_WRITE_DATA访问,并且附加写入在重叠结构中指定它(Offset = FILE_WRITE_TO_END_OF_FILE和OffsetHigh = -1记录在WDK)。
通过不同的句柄在写入之间正确同步追加行为。我经常使用它来记录多个进程。我会在每次打开时写入BOM以抵消0,并附加所有其他写入。时间戳不是问题,可以在需要时对它们进行排序。
答案 1 :(得分:2)
即使追加是原子的(我不相信它),它也可能无法给你想要的结果。例如,假设日志包含时间戳,则期望在较旧的日志之后附加更新的日志似乎是合理的。使用并发性时,此保证不成立 - 如果多个进程正在等待写入同一文件,则其中任何一个都可能获得写锁定 - 而不仅仅是最旧的等待。因此,日志可以不按顺序写出。
如果这不是理想的行为,则可以通过将所有进程中的日志条目发布到共享队列(例如命名管道)来避免此行为。然后,您有一个从此队列写入日志文件的进程。这样可以避免出现并发问题,确保日志按顺序写入,并在文件追加不是原子时工作,因为文件只能由一个进程直接写入。
答案 2 :(得分:1)
从MSDN page创建和打开文件:
应用程序还使用CreateFile来指定是否要共享文件以进行读取,写入,或两者兼而有之。这称为共享模式。未共享的打开文件( dwShareMode 设置为零)无法通过打开它的应用程序或其他应用程序再次打开,直到其句柄已关闭。这也称为独占访问。
和
如果指定的访问或共享模式与上一次调用中指定的模式冲突,则CreateFile将失败。
因此,如果您使用CreateFile
而不是说File.Open
对文件访问没有相同级别的控制权,那么您应该能够以这样的方式打开文件不被其他进程破坏。
您显然必须向您的流程添加代码,以应对他们无法获得对日志文件的独占访问权的情况。
答案 3 :(得分:0)
不,不是。如果需要,Windows Vista / 7中有Transactional NTFS。