我有一个函数应该通过将所有文件从源文件复制到目标文件夹来创建源文件夹的备份。该函数使用由FindFirstFile
/ FindNextFile
驱动的while循环,然后为CopyFile
函数找到的每个文件调用Find...
。
现在,当源文件夹是SMB网络路径时(无论我是使用映射驱动器还是UNC路径),有时会发生FindNextFile
“看到”文件,但CopyFile
拒绝复制文件。错误代码为2,即ERROR_FILE_NOT_FOUND
。
我发现这很难相信,所以我在调用_access
之前向备份函数添加了对CopyFile
的调用,该函数检查文件是否存在。结果与CopyFile
相同,即_access
报告文件不存在(返回码-1和errno
为2,即ENOENT
)。
所以我的主要问题是:FindFirstFile
/ FindNextFile
“看到”CopyFile
和_access
都看不到的网络文件夹上的文件怎么可能?< / p>
其他信息/诊断:
CopyFile
和_access
在重试约4秒后突然开始看到有问题的文件。这向我表明确实存在某种网络延迟。似乎FindFirstFile
/ FindNextFile
访问网络路径的方式与CopyFile
/ _access
不同。不幸的是,我对这种效果的研究没有发现任何有用的信息,所以我只能推测。如果FindFirstFile
/ FindNextFile
/ CopyFile
确实不能很好地协同工作,您是否知道一组更有效的查找/复制API函数?
答案 0 :(得分:7)
这可能是因为Windows上的SMB 2.0维护了一个只能每10秒刷新一次的缓存。
有关详细信息和计划性工作,请参阅this blog文章。
它声明:
这是因为客户端包含的本地缓存 SMB 2.0。创建SMB 2.0会话时,本地缓存 将在客户端提供,之后将刷新 默认情况下每10秒。存在对该文件的任何进一步请求 将针对此本地缓存进行检查,而不是转到 服务器共享。因此,如果在客户端和服务器上构建本地缓存 创建共享新文件,本地缓存未被无效 不与服务器共享同步,任何进一步的检查请求 新文件存在将失败。这是根本原因,但是设计。如果 更新本地缓存并与服务器共享同步,请求将 成功。
对于解决方案/解决方法,链接文章提到:
如何控制本地缓存生命周期?
您可以在下方创建注册表项以控制缓存生存期。
在
下HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \服务\ LanmanWorkstation \参数:
FileInfoCacheLifetime
FileNotFoundCacheLifetime
DirectoryCacheLifetime
它们都是REG_DWORD类型,以秒为单位。
程序化解决方法?
使用Win32 API注册目录或文件更改通知。
使用FindFirstChangeNotification Function(Windows)API进行注册 变化。