Windows CloseHandle函数调用和SMB关闭请求之间的延迟

Windows CloseHandle函数调用和SMB关闭请求之间的延迟,windows,smb,Windows,Smb,下面的代码位打开SMB共享上的文件,并立即将其关闭。出于某种原因,我看到CloseHandle调用和SMB Close请求之间存在延迟,这两个请求是通过网络发送的 #include <Windows.h> #include <stdio.h> typedef NTSTATUS (__stdcall *NtQuerySecurityObjectPtr)( _In_ HANDLE Handle, _In_ SECURITY_I

下面的代码位打开SMB共享上的文件,并立即将其关闭。出于某种原因,我看到CloseHandle调用和SMB Close请求之间存在延迟,这两个请求是通过网络发送的

#include <Windows.h>
#include <stdio.h>

typedef NTSTATUS (__stdcall *NtQuerySecurityObjectPtr)(
    _In_  HANDLE               Handle,
    _In_  SECURITY_INFORMATION SecurityInformation,
    _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
    _In_  ULONG                Length,
    _Out_ PULONG               LengthNeeded
    );

void printTime() {
    SYSTEMTIME time;
    GetSystemTime(&time);
    int required = GetTimeFormat(LOCALE_INVARIANT, 0, &time, nullptr, nullptr, 0);
    LPTSTR buffer = (LPTSTR)GlobalAlloc(GPTR, required * sizeof(TCHAR));
    GetTimeFormat(LOCALE_INVARIANT, 0, &time, nullptr, buffer, required);
    wprintf(L"%s\n", buffer);
}

int main()
{
    LPCTSTR file = L"\\\\192.168.13.163\\share\\file1";
    HANDLE f = INVALID_HANDLE_VALUE;


    f = CreateFile(
        file,
        GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr,
        CREATE_ALWAYS,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN,
        INVALID_HANDLE_VALUE
        );
    CloseHandle(f);
    printTime();

    return 0;
}
在CloseHandle调用之后立即运行相同的命令将导致找不到句柄

C:\Users\pepijn\Desktop>Handle.exe file1

Handle v4.0
Copyright (C) 1997-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

No matching handles found.
有人知道这次延误的原因吗


关于这个话题,我能找到的最密切相关的问题是。公认的答案是,其他进程可能会保留该文件。如上所述,我认为这里不是这样。我没有运行任何病毒扫描程序,我希望任何打开的句柄都会显示在句柄的输出中,因为它是以提升的权限运行的。

这显然是由于服务器在文件打开时授予的批操作锁定(或相对租约)。您可以通过使用Wireshark检查创建响应来证明这一点


避免批处理oplock被授予的建议技巧之一是在原始CreateFile调用之前打开同一个文件以在另一个应用程序中读取

这显然是由于服务器在文件打开时授予批处理Oplock(或相对租约)。您可以通过使用Wireshark检查创建响应来证明这一点


避免批处理oplock被授予的建议技巧之一是在原始CreateFile调用之前打开同一个文件以在另一个应用程序中读取

多亏了第一个答案,我才更清楚该去哪里找。据我所知,这是Windows SMB重定向程序中的故意行为。它有一个打开的文件句柄缓存,每x秒获取一次。这样做是为了透明地优化经常打开/关闭/重新打开文件的应用程序。有许多注册表项会影响这一点(请参阅),但它们似乎都不会导致CloseHandle上的SMB立即关闭请求。
我能得到的最好结果是将CacheFileTimeout设置为0。这仍然会留下3-5秒的延迟(可能取决于清理计时器的触发频率)。

多亏了第一个答案,我才更清楚地知道应该在哪里查找。据我所知,这是Windows SMB重定向程序中的故意行为。它有一个打开的文件句柄缓存,每x秒获取一次。这样做是为了透明地优化经常打开/关闭/重新打开文件的应用程序。有许多注册表项会影响这一点(请参阅),但它们似乎都不会导致CloseHandle上的SMB立即关闭请求。 我能得到的最好结果是将CacheFileTimeout设置为0。这仍然会留下3-5秒的延迟(可能取决于清理计时器的触发频率)。

这不完全是一个答案(抱歉),但我认为本地文件也可能会出现这种情况。我正在开发一个在Windows和Linux上运行的测试套件,在这个套件中,它打开一个旧文件,读取其内容,编写一个新文件,关闭旧文件,然后在上面重命名

在Unix上,这很好,因为我们可以重命名现有文件,甚至是打开的文件。在Windows上,如果我不先关闭文件句柄,这些测试将可靠地失败。然而,即使我这样做了,测试也会有10%的时间随机失败,比如:

TRACE:尝试创建测试文件/0\u 0\backup\01234567\refcount.rdb.rfw使用dwShareMode文件共享读取文件共享写入
[检查修复]警告:引发异常:在C:\projects\boxbackup\lib\backupstore\BackupStoreRefCountDatabase.cpp:200处,CommonException(OSFileError)(未能将临时refcount数据库文件从testfiles/0_0\backup\01234567\refcount.rdb.rfwX重命名为testfiles/0_0\backup\01234567\refcount.rdb.rfw。(5))处的CommonException(OSFileError)

我知道在重命名该文件之前,我使用
CloseHandle()
关闭该文件。这些症状可以用异步发生的
CloseHandle()
来很好地解释,但到目前为止,我的经验和这个问题是我所掌握的可能发生这种情况的唯一证据。这是一个本地文件系统,而不是SMB(我认为,因为AppVeyor的内部对我来说有点像一个黑盒子)

编辑:我在以下内容中找到了确认和解释:

我相信这已经包括在内了。简而言之,即使您在文件句柄上调用了CloseHandle,内核仍然可能有未完成的引用,需要几毫秒才能关闭

不完全是答案(抱歉),但我认为本地文件也可能出现这种情况。我正在开发一个在Windows和Linux上运行的测试套件,在这个套件中,它打开一个旧文件,读取其内容,编写一个新文件,关闭旧文件,然后在上面重命名

在Unix上,这很好,因为我们可以重命名现有文件,甚至是打开的文件。在Windows上,如果我不先关闭文件句柄,这些测试将可靠地失败。然而,即使我这样做了,测试也会有10%的时间随机失败,比如:

TRACE:尝试创建测试文件/0\u 0\backup\01234567\refcount.rdb.rfw使用dwShareMode文件共享读取文件共享写入
[检查修复]警告:引发异常:在C:\projects\boxbackup\lib\backupstore\BackupStoreRefCountDatabase.cpp:200处,CommonException(OSFileError)(未能将临时refcount数据库文件从testfiles/0_0\backup\01234567\refcount.rdb.rfwX重命名为testfiles/0_0\backup\01234567\refcount.rdb.rfw。(5))处的CommonException(OSFileError)

我知道在重命名该文件之前,我使用
CloseHandle()
关闭该文件。这些症状可以用异步发生的
CloseHandle()
来很好地解释,但到目前为止,我的经验和这个问题是我所掌握的可能发生这种情况的唯一证据。这是一个本地文件系统,而不是SMB(我认为,因为AppVeyor的内部对我来说有点像一个黑盒子)

编辑:我在以下内容中找到了确认和解释:

我相信我
C:\Users\pepijn\Desktop>Handle.exe file1

Handle v4.0
Copyright (C) 1997-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

No matching handles found.