【发布时间】:2018-02-11 07:13:57
【问题描述】:
我正在使用 Windows 上的文件映射,但遇到了一些问题。 首先,我需要部分映射文件并动态设置文件的开头和结尾。
我的代码如下:
long fiveMB = 5 * pow(2, 20);
for(int i=0;i<parts;i++){
long start = (i)*fiveMB;
long end = (i + 1)*fiveMB;
long realEnd = end;
if (roundedDim<realEnd)
realEnd = dim;
long chunkDim = realEnd - start;
LARGE_INTEGER fileMapStart.QuadPart = (start/granularity)*granularity;
LARGE_INTEGER mapViewSize.QuadPart = (start%granularity) + chunkDim;
LARGE_INTEGER fileMapSize.QuadPart = start + chunkDim;
long offset = start - fileMapStart.QuadPart;
HANDLE fileMappingH= CreateFileMapping(fileH, NULL, PAGE_READONLY, fileMapSize.HighPart, fileMapSize.LowPart, NULL);
if(fileMappingH == INVALID_HANDLE_VALUE || fileMappingH == NULL){
printf("Error mapping file: %d\n",GetLastError());
CloseHandle(fileH);
return 1;
}
char *mapView = (char *)MapViewOfFile(fileMappingH, FILE_MAP_READ, fileMapStart.HighPart, fileMapStart.LowPart, mapViewSize.QuadPart);
if ((LPVOID)mapView == NULL) {
printf("Error mapView: %d\n", GetLastError());
CloseHandle(fileMappingH);
CloseHandle(file);
return 1;
}
mapView += offset;
/* doing all the stuff */
UnmapViewOfFile((LPVOID)mapView);
CloseHandle(fileMappingH);
}
据我所知,只有 MapViewOfFile 要求起始字节与系统粒度对齐,所以我没有费心为此修复最大文件映射大小。
我在通过 GlobalMemoryStatusEx(&memstatus) 和 memstatus.ullAvailVirtual 计算可用内存时在 1448 KB 文件上尝试了此代码(打印出暗淡我得到 1482159 字节)我得到 2092208128 字节,但仍然坚持 CreateFileMapping 调用失败,错误代码为 8,ERROR_NOT_ENOUGH_MEMORY。
我也尝试调用 CreateFileMapping(fileH, NULL, PAGE_READONLY, 0, 0, NULL) 来对整个文件进行内存映射,但是 MapViewOfFile 出现了问题,错误 5,ERROR_ACCESS_DENIED。
我不明白我在这里做错了什么,因为我在同一个项目的 Linux 版本上使用 mmap 成功地做到了。
感谢任何可能提供帮助的人。
编辑:
c 是剩菜,我的意思是我
添加了 UnmapViewOfFile 和 CloseHandle 调用
【问题讨论】:
-
c 未定义。
-
一开始 - 在循环中调用
CreateFileMapping- 这是设计错误。你只需要调用一次。在第二个错误CreateFileMapping返回 0 但不是INVALID_HANDLE_VALUE- 没有意义检查INVALID_HANDLE_VALUE -
关于错误
ERROR_NOT_ENOUGH_MEMORY- 几个 ntstatus 代码被转换为这个错误。所以这里在win32层上丢失了。需要调用RtlGetLastNtStatus()- 可能是你得到例如STATUS_SECTION_TOO_BIG- 这意味着你设置的部分大小超过文件大小,因为你使用PAGE_READONLY文件不能扩展 -
@ifelsemonkey 文件映射使用的唯一 RAM 是
MapViewOfFile调用指定的 RAM;因此,如果您知道哪个是正确的文件偏移量以及要从那里检查多少字节,您只需正确指定MapViewOfFile的最后一个参数即可,在我的代码中为mapViewSize.QuadPart。 Here你可以看到整个代码,链接到奇特的MapViewOfFile函数调用 -
@ifelsemonkey 是的,但是在
CreateFileMapping中您必须输入整个文件大小;为了检查给定偏移量的 3 个字节,必须通过MapViewOfFile指定:请注意,此类调用中涉及的每个大小都必须与文件系统粒度对齐!因此,如果要读取这 3 个字节,则必须映射以预期粒度正确开始的文件块,大小为 3 个字节,然后考虑偏移量以本地化此类字节
标签: c file winapi memory mapping