该文件特别使用’临时’文件属性创建,鼓励Windows将文件保留在系统缓存中。这意味着文件读取的大部分时间不会靠近磁盘,而是会从系统缓存中读取文件的一部分。
所以这里有两个问题:
> Windows可以从不同的线程同时访问同一个文件?
>如果是这样,你如何提供这种能力?我已经尝试创建临时文件并再次打开该文件以提供两个文件句柄,但第二个打开不成功。
这里是创建:
FFileSystem := CreateFile(PChar(FFileName),GENERIC_READ + GENERIC_WRITE,FILE_SHARE_READ + FILE_SHARE_WRITE,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL OR FILE_FLAG_RANDOM_ACCESS OR FILE_ATTRIBUTE_TEMPORARY OR FILE_FLAG_DELETE_ON_CLOSE,0);
这是第二次开放:
FFileSystem2 := CreateFile(PChar(FFileName),GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,0);
到目前为止,我已经尝试过各种标志的组合,没有成功。第二个文件打开总是失败,消息影响该文件无法被其他进程使用的文件访问。
编辑:
好的,一些更多的信息(我希望不要迷失在这里的杂草…)
所涉及的过程是WinXP 64上运行的Win32服务器进程。它维护大型空间数据库,并希望在L1 / L2缓存结构的内存中尽可能多地保留空间数据库。 L1已经存在。 L2作为一个“临时”文件存在于Windows系统缓存中(有点像肮脏的技巧,但是有一些Win32内存限制)。 Win64意味着我可以使用系统缓存大量的内存,因此用于保存L2缓存的内存将计入进程内存。
多个(可能很多)线程想要并发访问包含在L2缓存中的信息。目前,访问是序列化的,这意味着一个线程可以读取它的数据,而大多数(或其余的)线程在该操作完成之前被阻塞。
L2缓存文件确实写入,但是我很高兴全局串行/交错读写类型操作,只要我可以执行并发读取。
我知道有一个讨厌的潜在的线程并发问题,我知道有几十种方法来皮肤这只猫在其他情况下。我有这个特定的上下文,我正在尝试确定是否有一种方法允许并发线程读取访问文件和同一进程。
我考虑过的另一种方法是将L2缓存分成两个临时文件,其中每个文件以当前单个L2缓存文件的方式连接线程访问。
是的,这个有点绝对的做法是因为64位德尔福不会随时与我们在一起:-(
谢谢,
雷蒙德。
解决方法
TMultiReadExclusiveWriteSynchronizer
来控制对整个文件的访问。比起一个关键部分,它的序列化程度要小一些。要进行更精细的控制,请查看
LockFileEx
以根据需要控制对文件特定区域的访问。写作时请求专属锁;当阅读时,共享锁。
对于您发布的代码,在初始共享标志中指定File_Share_Write意味着所有后续的打开操作也必须共享用于写入的文件。报价the documentation:
If this flag is not specified,but the file or device has been opened for write access or has a file mapping with write access,the function fails.
您的第二个开放请求是说,它不希望任何人被允许写入该文件,而该句柄保持打开。既然已经有另一个句柄打开了,那么允许写入,第二个请求就无法实现了。 GetLastError应该返回32,这是Error_Sharing_Violation,正是文档说明应该发生的。
指定File_Flag_Delete_On_Close表示所有后续打开的请求需要共享要删除的文件。文件再次:
Subsequent open requests for the file fail,unless the
FILE_SHARE_DELETE
share mode is specified.
然后,由于第二个打开请求共享要删除的文件,所有其他打开的句柄也必须共享才能删除。文件:
If there are existing open handles to a file,the call fails unless they were all opened with the
FILE_SHARE_DELETE
share mode.
FFileSystem := CreateFile(PChar(FFileName),Generic_Read or Generic_Write File_Share_Read or File_Share_Write or File_Share_Delete,Create_Always,File_Attribute_Normal or File_Flag_Random_Access or File_Attribute_Temporary or File_Flag_Delete_On_Close,0); FFileSystem2 := CreateFile(PChar(FFileName),Generic_Read,File_Share_Read or File_Share_Write or File_Share_Delete,Open_Existing,0);
换句话说,除了第五个参数之外,所有的参数是相同的。
这些规则适用于在同一线程上打开的两次尝试以及来自不同线程的尝试。