在我们的应用程序中,我们必须经常在远程计算机上(在同一LAN段中)写入大文件(100 MB到某些GB)。这是我们应用程序的瓶颈。远程计算机可能是本机Windows,也可能是使用SMB的Linux计算机。
我们发现,使用Windows API函数CopyFile首先在本地创建文件,然后将其复制比使用CreateFile直接将UNC路径(或驱动器号)定位到远程计算机要快得多。但是,我们仍然必须进行两次写操作,这似乎远非最佳。
受此问题的第一条评论的启发,我实现了here和here所讨论的CreateFile的FILE_FLAG_OVERLAPPED用法:
HANDLE hToken;
auto openResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!openResult)
{
gConsoleAndLog << "OpenProcessToken failed with err " << GetLastError() << std::endl;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 3;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[2].Attributes = SE_PRIVILEGE_ENABLED;
if(! LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &tp.Privileges[0].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_MANAGE_VOLUME_NAME failed with err " << GetLastError() << std::endl;
if (! LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, &tp.Privileges[1].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_INCREASE_QUOTA_NAME failed with err " << GetLastError() << std::endl;
if (! LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &tp.Privileges[2].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_ASSIGNPRIMARYTOKEN_NAME failed with err " << GetLastError() << std::endl;
auto adjustResult = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
if (!adjustResult || GetLastError() != ERROR_SUCCESS)
{
gConsoleAndLog << "AdjustTokenPrivileges failed with err " << GetLastError() << std::endl;
}
else gConsoleAndLog << "AdjustTokenPrivileges SUCCESS" << std::endl;
与第二篇文章不同,即使以管理员身份开始,我也无法设置特权“ SE_ASSIGNPRIMARYTOKEN_NAME”。我不知道这有什么区别。
使用FILE_FLAG_NO_BUFFERING打开文件后| FILE_FLAG_OVERLAPPED,计算的大小已预先分配:
auto setFileErr = SetFilePointerEx(hFile, endPosition, NULL, FILE_BEGIN);
if (setFileErr == INVALID_SET_FILE_POINTER)
{
CPrintWithOSError(NULL, 0, "SetFilePointerEx FAILED");
return 1;
}
if (!SetEndOfFile(hFile))
{
CPrintWithOSError(NULL, 0, "SetEndOfFile FAILED");
return 1;
}
if (!SetFileValidData(hFile, endPosition.QuadPart))
{
CPrintWithOSError(NULL, 0, "SetFileValidData FAILED");
return 1;
}
这适用于本地驱动器,但是SetFileValidData在远程驱动器上失败。
呼叫失败并显示Windows错误
1314 a required privilege is not held by the client
答案 0 :(得分:0)
如果您可以访问tifflib源代码,则应该能够通过缓冲要写入输出文件的数据来解决此问题,直到缓冲区已满或文件已关闭。一个简单的FILE *
就能做到这一点,使用setvbuf
将缓冲区大小设置为1MB左右。