如何在进程间锁定/解锁文件?

7

在Linux上使用运行在mono上的C#代码时,注意以下代码在Windows上可以跨进程锁定文件,但在Linux上通过mono(ubuntu 14.04)无法实现。

new FileStream("myfile.lock",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);

从互联网上的研究来看,我应该可以使用咨询锁来完成这项任务。

FileStream.Lock

然而,它无法正常工作。在Ubuntu 14.04上测试了两个进程,它们都可以执行"FileStream.Lock(0, int.MaxValue)"。根据源代码,我本来希望后一个进程会因异常而失败。是否有任何解决方案?

当你说它不起作用时,你是指什么?因为使用“咨询锁定(advisory lock)”,任何其他进程都可以更新该文件(只要它具有安全访问权限)。FYI: FileStream.Lock (通过Mono) 使用 fcntlF_SETLK - SushiHangover
@SushiHangover,我更新了我的问题,更详细地描述了“不起作用”的情况。我测试了两个进程,它们都尝试执行“FileStream.Lock”,我原本期望其中一个会抛出错误,但实际上没有。 - Xiaomin Wu
1个回答

6

从mono邮件列表 "http://mono.1490590.n4.nabble.com/File-Locking-td4663839.html"获取帮助。

以下是来自 "Edward Ned Harvey (mono)" 的回答引用:

有点类似。 根本问题在于OSX、Linux和Windows都有不同的基础文件锁定结构,当然,还有一些关于使用哪个文件系统的变量。 我没有彻底弄清楚每个操作系统或文件系统的所有答案,也不知道在哪种情况下这将足够好,但这就是我最终使用的方式,在我们需要它工作的条件下有效:

using (var foo = new FileStream(filePath, FileMode.Open,FileAccess.ReadWrite, FileShare.None)) { // must include Write access in order to lock file 
    foo.Lock(0, 0); // 0,0 has special meaning to lock entire file regardless of length 
}

对于Windows系统,只需指定FileAccess和FileShare即可。对于Linux系统,至少在ext4文件系统下,无论您为FileAccess和FileShare指定什么,文件都可以同时读取。Lock()方法执行柔性锁定。它不是由操作系统强制执行的,但至少我们尝试过的所有情况中,其他客户端应用程序都会尊重该锁定。没有进一步深入研究。

1
如果使用锁的进程异常退出,这会在 Mono Linux 上释放锁吗? - user3791372
1
是的,它释放了在Mono Linux上的锁定。 - Radu Damian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接