CloseHandle 函数调用和 SMB 关闭请求之间的延迟 [英] Delay between CloseHandle function call and SMB Close request

查看:29
本文介绍了CloseHandle 函数调用和 SMB 关闭请求之间的延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码在 SMB 共享上打开一个文件并立即关闭它.出于某种原因,我发现 CloseHandle 调用和通过网络发送的 SMB 关闭请求之间存在延迟.

The bit of code below opens a file on an SMB share and closes it immediately. For some reason I'm seeing a delay between the CloseHandle call and the SMB Close request being sent over the wire.

#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;
}

我用调试器运行了这段代码,并在 printTime 调用后立即放置了一个断点.在此 printTime 的一次测试运行中,输出 12:18:11.在 Wireshark 中,我看到相应的关闭请求在 12:18:20 发出.所以在函数调用和消息发出之间有大约 10 秒的延迟.

I ran this code with a debugger and put a breakpoint right after the printTime call. In one test run of this printTime outputs 12:18:11. In Wireshark I see the corresponding Close request being sent out at 12:18:20. So there's about 10s delay between the function call and the message being sent out.

我认为这可能是由于某个句柄在某处泄露或某个其他进程将文件句柄保持打开状态,但我认为并非如此.如果我在 CloseHandle 调用之前停止程序,则在系统用户 shell 中执行的 sysinternals 句柄工具会向我显示我的进程具有该文件的句柄

I thought this might be due to a handle being leaked somewhere or some other process keeping a handle to the file open, but I don't think that's the case. If I halt the program right before the CloseHandle call, the sysinternals handle tool, executed in a system user shell, shows me that my process has a handle to the file

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

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

SmbClose.exe       pid: 7020   type: File            C8: \Device\Mup\192.168.13.163\DMTest_share\file1

在 CloseHandle 调用后立即运行相同的命令导致找不到句柄

Running the same command right after the CloseHandle call results in no handles being found

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

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

No matching handles found.

有谁知道这个延迟的原因是什么?

Does anyone know what could be the cause of this delay?

我能找到的与此主题最接近的相关问题是 FileStream.Close() 不会立即关闭文件句柄.那里接受的答案是其他一些进程可能会保留该文件.如上所述,我认为这里不是这种情况.我没有运行任何病毒扫描程序,我希望在 Handle 的输出中显示任何打开的句柄,因为它以提升的权限运行.

The closest related question on this topic I could find is FileStream.Close() is not closing the file handle instantly. The accepted answer there is that some other process might be holding on to the file. As stated above, I don't think that's the case here. I don't have any virus scanners running and I would expect any open handles to show up in the output of Handle since it's running with elevated privileges.

推荐答案

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

This is apparently due to Batch Oplock (or relative Lease) granted by the server on file open. You can prove this by inspecting Create response with Wireshark.

避免在原始 CreateFile 调用之前打开同一文件以在另一个应用程序中读取的批处理机会锁被授予的推荐技巧之一.

One of recommended tricks to avoid batch oplocks being granted si opening the same file for reading in another application right before your original CreateFile call.

这篇关于CloseHandle 函数调用和 SMB 关闭请求之间的延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆