锁定文件,使其无法删除

时间:2010-04-07 01:44:29

标签: c++ c

我正在Windows上使用两个独立的c / c ++应用程序,其中一个应用程序不断更新磁盘上的图像(来自网络摄像头),另一个读取该图像进行处理。 99.99%的时间都可以正常工作,但是当读者删除它以用新的刷新它时,读者应用程序每隔一段时间就会读取图像。

对我来说,显而易见的解决方案似乎是让读者对文件进行某种锁定,以便编写者可以看到它无法删除它并因此旋转锁定它直到它可以删除和更新。反正有没有这样做?或者是否有另一种简单的设计模式可用于在两个程序之间刷新相同类型的常量图像?

谢谢,

-Robert

7 个答案:

答案 0 :(得分:4)

尝试使用同步对象,可能是互斥锁。每当进程想要读取或写入文件时,它应首先获取互斥锁。

答案 1 :(得分:3)

是的,锁定机制会有所帮助。不幸的是,有几个可供选择。 Linux / Unix,例如有flock(2),Windows有类似(但不同)的机制。

另一个(有些hacky)解决方案是只用临时名称编写文件,然后重命名它。许多文件系统保证重命名是原子的,所以这可能有效。然而这取决于fs,所以它有点hacky。

答案 2 :(得分:3)

如果您愿意使用Windows API,则使用CreateFile打开文件并为dwShareMode传入0将不允许任何其他应用程序打开该文件。

来自文档:

  

防止其他进程打开文件或设备   请求删除,读取或写入访问。

然后你必须使用ReadFile,WriteFile,CloseFile等而不是C标准库函数。

答案 3 :(得分:2)

或者,作为一个非常简单的kludge,读者在开始阅读之前创建一个临时文件(说.lock)并在之后删除它。只要.lock存在,写操作就不会操纵文件。

Open Office就是这样做的(以及其他人),无论在哪个平台上,它都可能是最简单的。

答案 4 :(得分:2)

乔,提出了许多解决方案;我评论了其中的一些,但我想提出一个全面的观点和一些细节和建议:

您有以下选择:

  1. 使用文件系统锁定:在Windows下打开阅读器和编写器(并分别使用CREATE_ALWAYS disposition创建) OF_SHARE_EXCLUSIVE mode中的共享文件;让读者和作者准备好处理ERROR_SHARING_VIOLATION并在一段预定义的时间后重试(例如250ms)
  2. 使用文件重命名实质上转移文件所有权:让编写者创建编写者私有文件(例如shared_file.tmpwrite),写入,关闭它,然后通过将其重命名为商定的“公共”名称(例如,简单shared-file),将其公开提供给读者;让读者定期测试具有商定的“公共”名称(例如shared-file)的文件的存在,并且当找到一个时,尝试首先将其重命名为<在读者打开它之前(在读者私人名称下);强>读者私人名称(例如shared_file.tmpread);在Windows use MOVEFILE_REPLACE_EXISTING下;重命名操作不必是原子的,以使其正常工作
  3. 使用其他形式的interprocess communication (IPC) :在Windows下,您可以create a named mutex,并让读者和作者都尝试创建(如果已经存在,则会返回现有的互斥锁exists)然后在打开共享文件进行读取或写入之前获取命名的互斥锁
  4. 实施您自己的文件系统支持的锁定:利用open(O_CREAT|O_EXCL)或在Windows下,CREATE_NEW disposition原子创建应用程序lock file;与上面的OF_SHARE_EXCLUSIVE方法不同,您可以自行处理陈旧的锁定文件(即锁定文件的文件,这些文件没有正常关闭,例如崩溃后。)
  5. 实施方法1

    方法2也可以,但它在某种意义上重新发明轮子。

    方法3可以说有一个优点,就是允许你的读者进程等待写入过程,反之亦然,从而消除了方法1和2重试之间任意睡眠延迟的需要(轮询);但是,如果您对轮询没问题,那么您仍然应该使用方法1

    方法4仅为完整性而列出,因为它实现起来很复杂(当检测到锁定文件过时时,例如通过检查其中包含的PID是否仍然存在,多个进程可能会竞争其被删除,引入了需要第二次锁定的竞争状态,这又可能变得陈旧等等,例如:

    • 进程A创建锁定文件但在不删除锁定文件的情况下死亡
    • 进程A重新启动并尝试获取锁定文件,但意识到它已过时
    • 进程B出现睡眠延迟,并尝试获取锁定文件,但意识到它已过时
    • 进程A删除锁定文件,它知道它已过时,并重新创建它基本上重新获取锁定
    • 进程B删除锁定文件,它仍然认为是陈旧的(尽管此时它已不再陈旧且由进程A拥有) - 违规

答案 5 :(得分:0)

不是删除图像,而是将它们附加到文件末尾?这将允许您在读取器仍在运行时继续添加到文件而不会破坏文件。然后,读者可以在完成图像时删除图像(如果有必要)并移动到下一图像。或者,另一个选项是将图像存储在缓冲区中,以便进行写入,并测试文件指针。如果它设置为文件的头部,那么您可以继续从缓冲区写入文件。否则,请等待读取器完成并将指针放回文件头部。

答案 6 :(得分:0)

你不能存储几张图片吗? ('n'听起来像一个很好的数字: - )

填充你的磁盘并不是太多,但肯定3就足够了?如果没有,你的写作速度比你可以处理得快,并且有一个基本的问题(发现'n')。

循环覆盖。