C++ 如何使用ReadFileScatter
我一直在尝试在我的代码中使用今天(这听起来正是我所需要的),到目前为止没有很多运气。用谷歌搜索互联网上的错误并没有给我太多的洞察力 文件规定: 数组必须包含足够的元素来存储nNumberOfBytesToRead字节的数据,加上一个元素用于终止NULL。例如,如果要读取40 KB的数据,且页面大小为4 KB,则该数组必须有11个元素,其中10个元素表示数据,1个元素表示NULL 每个缓冲区的大小必须至少等于系统内存页的大小,并且必须在系统内存页大小边界上对齐。系统将一个系统内存页的数据读入每个缓冲区 该函数按顺序将数据存储在缓冲区中。例如,它将数据存储到第一个缓冲区中,然后再存储到第二个缓冲区中,依此类推,直到每个缓冲区都被填满并存储所有数据,或者不再有缓冲区 到目前为止,我一直在尝试这样做。我使用C++ 如何使用ReadFileScatter,c++,winapi,asynchronous,readfile,C++,Winapi,Asynchronous,Readfile,我一直在尝试在我的代码中使用今天(这听起来正是我所需要的),到目前为止没有很多运气。用谷歌搜索互联网上的错误并没有给我太多的洞察力 文件规定: 数组必须包含足够的元素来存储nNumberOfBytesToRead字节的数据,加上一个元素用于终止NULL。例如,如果要读取40 KB的数据,且页面大小为4 KB,则该数组必须有11个元素,其中10个元素表示数据,1个元素表示NULL 每个缓冲区的大小必须至少等于系统内存页的大小,并且必须在系统内存页大小边界上对齐。系统将一个系统内存页的数据读入每个缓
VirtualAlloc
(确保页面边界约束)分配了一组字节,在列表中添加了一个终止符NULL,确保磁盘上的数据位于系统边界上(隐式地是磁盘扇区大小边界),并发出调用
无需进一步说明,以下是C++中的最低测试用例:
// Setup: c:\tmp\test.dat is a file with at least 12K of stuff.
// I attempt to read page 2/3, e.g. offset [4096-4096+8192>
// TEST:
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
auto pageSize = systemInfo.dwPageSize;
std::cout << "Page size: "<< pageSize << std::endl;
// Allocate 2 pages that are aligned with one in the middle:
auto buffer = reinterpret_cast<char*>(VirtualAlloc(NULL, pageSize * 3, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
// Create read buffer:
std::vector<FILE_SEGMENT_ELEMENT> elements;
{
FILE_SEGMENT_ELEMENT element1;
element1.Buffer = buffer;
elements.push_back(element1);
}
{
FILE_SEGMENT_ELEMENT element2;
element2.Buffer = buffer + pageSize * 2;
elements.push_back(element2);
}
{
FILE_SEGMENT_ELEMENT terminator;
terminator.Buffer = NULL;
elements.push_back(terminator);
}
// [..] Physical sector size is normally checked as well. In my case it's 512 bytes,
// so I guess that's irrelevant here.
//
// Open file:
auto fileHandle = CreateFile(
"c:\\tmp\\test.dat",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
auto err = GetLastError();
if (err != ERROR_ALREADY_EXISTS && err != ERROR_SUCCESS)
{
throw std::exception(); // FIXME.
}
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(OVERLAPPED));
LARGE_INTEGER tmp;
tmp.QuadPart = 4096; // Read from disk page 1
overlapped.Offset = tmp.LowPart;
overlapped.OffsetHigh = tmp.HighPart;
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
auto succes = ReadFileScatter(fileHandle, elements.data(), pageSize * 2, NULL, &overlapped);
err = GetLastError();
if (!succes && err != ERROR_IO_PENDING && err != ERROR_SUCCESS)
{
throw std::exception(); // The call always ends up here with error 87: Invalid parameter
}
WaitForSingleObject(overlapped.hEvent, INFINITE);
std::cout << "Call succeeded!" << std::endl;
// FIXME: Proper exception handling.
// Clean up:
VirtualFree(buffer, pageSize * 3, MEM_DECOMMIT | MEM_RELEASE);
CloseHandle(overlapped.hEvent);
CloseHandle(fileHandle);
//安装程序:c:\tmp\test.dat是一个至少包含12K内容的文件。
//我试图阅读第2/3页,例如偏移量[4096-4096+8192>
//测试:
系统信息系统信息;
GetSystemInfo(&systemInfo);
自动页面大小=systemInfo.dwPageSize;
std::如果你在问题文本中明确解释错误模式,会有帮助吗?你是对的,我应该(并将做出更改)。在代码中它说:调用总是以错误87结束:无效参数
。文件句柄必须使用通用读取权限创建,并且文件标志重叠和文件标志无缓冲标志。-在代码中文件标志重叠
在哪里?@RbMm Pfff…我不敢相信我已经盯了一整天。该死的…谢谢,这实际上就是解决方案!为什么不简单地FILE\u SEGMENT\u ELEMENT元素[3];
和ReadFileScatter(fileHandle,RTL\u NUMBER\u OF(elements)
?这里的std::vector是什么?它们是元素。data()==element1
?