我正在Windows上使用两个独立的c / c ++应用程序,其中一个应用程序不断更新磁盘上的图像(来自网络摄像头),另一个读取该图像进行处理。 99.99%的时间都可以正常工作,但是当读者删除它以用新的刷新它时,读者应用程序每隔一段时间就会读取图像。
对我来说,显而易见的解决方案似乎是让读者对文件进行某种锁定,以便编写者可以看到它无法删除它并因此旋转锁定它直到它可以删除和更新。反正有没有这样做?或者是否有另一种简单的设计模式可用于在两个程序之间刷新相同类型的常量图像?
谢谢,
-Robert
答案 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)
您有以下选择:
CREATE_ALWAYS
disposition创建) OF_SHARE_EXCLUSIVE
mode中的共享文件强>;让读者和作者准备好处理ERROR_SHARING_VIOLATION
并在一段预定义的时间后重试(例如250ms)shared_file.tmpwrite
),写入,关闭它,然后通过将其重命名为商定的“公共”名称(例如,简单shared-file
),将其公开提供给读者;让读者定期测试具有商定的“公共”名称(例如shared-file
)的文件的存在,并且当找到一个时,尝试首先将其重命名为<在读者打开它之前(在读者私人名称下);强>读者私人名称(例如shared_file.tmpread
);在Windows use MOVEFILE_REPLACE_EXISTING
下;重命名操作不必是原子的,以使其正常工作open(O_CREAT|O_EXCL)
或在Windows下,CREATE_NEW
disposition以原子创建应用程序lock file;与上面的OF_SHARE_EXCLUSIVE
方法不同,您可以自行处理陈旧的锁定文件(即锁定文件的文件,这些文件没有正常关闭,例如崩溃后。)我实施方法1 。
方法2也可以,但它在某种意义上重新发明轮子。
方法3可以说有一个优点,就是允许你的读者进程等待写入过程,反之亦然,从而消除了方法1和2重试之间任意睡眠延迟的需要(轮询);但是,如果您对轮询没问题,那么您仍然应该使用方法1
方法4仅为完整性而列出,因为它实现起来很复杂(当检测到锁定文件过时时,例如通过检查其中包含的PID是否仍然存在,多个进程可能会竞争其被删除,引入了需要第二次锁定的竞争状态,这又可能变得陈旧等等,例如:
答案 5 :(得分:0)
不是删除图像,而是将它们附加到文件末尾?这将允许您在读取器仍在运行时继续添加到文件而不会破坏文件。然后,读者可以在完成图像时删除图像(如果有必要)并移动到下一图像。或者,另一个选项是将图像存储在缓冲区中,以便进行写入,并测试文件指针。如果它设置为文件的头部,那么您可以继续从缓冲区写入文件。否则,请等待读取器完成并将指针放回文件头部。
答案 6 :(得分:0)
填充你的磁盘并不是太多,但肯定3就足够了?如果没有,你的写作速度比你可以处理得快,并且有一个基本的问题(发现'n')。
循环覆盖。