6

事情是这样的:我有两个应用程序,用 C++ 编写并在两台具有不同操作系统的机器上运行(一台 Linux 和一台 Windows)。其中一个过程负责更新 NAS(网络附加存储)上的 XML 文件,而另一个则读取该文件。

是否可以同步这两个进程以避免在修改文件的同时读取文件?

4

5 回答 5

9

您可以在执行写入之前创建的服务器上创建一个锁定文件,等待然后写入并在完成时删除。在读取文件之前让读取过程检查令牌。

编辑:为了解决评论,您可以实现双重检查锁定类型模式。让读者和作者都有一个锁定文件并在工作之前仔细检查,例如:

Reader:检查写锁定文件,创建读锁定文件,检查写锁定文件,如果存在则删除读文件并中止。

Writer:检查读锁定文件,创建写锁定文件,检查读锁定文件,如果存在则删除写锁定文件并中止。

这将阻止您的进程相互践踏,但可能会发生潜在的竞争条件,因为您可能会同时检查、创建和重新检查两个进程,但这不会导致数据以不一致的状态读取,但会导致两个进程都读取并编写进程以中止您指定的延迟

于 2009-01-23T09:33:14.703 回答
5

谢谢大家的答案。

最后我们设法解决了我们的问题,不是通过使用操作系统的锁定命令(因为我们不确定它们是否会正确传播到 NAS 头的操作系统),而是通过创建锁定目录而不是锁定文件。目录创建是原子操作,如果文件夹已经存在则返回错误值。因此,我们不必在获取锁之前检查它是否存在,这两个操作都是一步完成的。

于 2009-01-26T09:03:03.690 回答
2

好的,您需要某种形式的锁定机制来控制访问。

大多数 *nix 文件系统都提供此功能。我怀疑它在 Windows 文件系统上也可用(因为 perl 使用了这种机制),但它可能有另一个名称。

看一下flock()。
这是一种文件锁定机制。它是一种建议锁,因此它实际上不会锁定文件并阻止使用,但它提供了一种标记文件的机制。如果两个应用程序都使用该机制,那么您可以控制对文件的访问。

flock() 提供共享锁(或读锁)和排他锁(或写锁)。flock 将阻塞您的线程(以非忙碌方式),直到用户解锁文件(它还提供非阻塞检查,因此您可以在等待时做其他事情)。

查看手册页第 2 节中的羊群。

int     flock(int fd, int operation);

Flock() applies or removes an advisory lock on the file associated with the file
descriptor fd.  A lock is applied by specifying an operation parameter that is
one of LOCK_SH or LOCK_EX with the optional addition of LOCK_NB.  To unlock an
existing lock operation should be LOCK_UN.
于 2009-01-23T13:05:56.380 回答
1

如果文件驻留在 NFS 共享上,您可以使用fcntl(2)锁定文件。检查Linux NFS FAQ中的问题D10。我对 Windows API 的经验很少,但据我所知,它们具有良好的 POSIX 支持,因此只要它们支持 POSIX.1-2001,您就应该能够使用 fcntl。

如果您使用不同的协议(即 AFS 或 SMB)访问文件,也许您可​​以设置一个简单的同步服务器,通过 IPC 接口管理锁?

于 2009-01-23T09:40:34.670 回答
1

是否可以从文件切换到数据库?

DBMS 可以很好地管理这种类型的并发性。它不需要昂贵或难以安装。MySql、Postgress 或 JavaDB 都可以以很少或没有成本优雅地处理这个问题。

如果数据库选项失败,我会让写入过程写入“隐藏”文件名,如“.updateinprogress.xml”,并在更新完成后重命名文件。在大多数系统上,“mv”或“ren”是一个原子操作,因此读取过程要么选择旧文件,要么选择新文件,但从来没有写过一半。

于 2009-01-23T09:53:23.740 回答