懂内存储器映射文件FileMapping的请进
懂内存映射文件FileMapping的请进!
我想写个分区逐扇区扫描的功能,之前使用CreateFile(“\\\\.\\D:”,...),是可以的,后来考虑到用ReadFile,WriteFile效率太差,决定一试内存映射文件。
但问题来了,CreateFile()这一步是成功的,但到了CreateFileMapping()时总报错,用GetLastError()查了下错误码,说是“参数不正确”。
将CreateFile(“\\\\.\\D:”,...)换成某个文件的话,比如CreateFile(“\\\\.\\D:\\aaa.dat”,...),再CreateFileMapping()就是成功的。期间,由于报错说“参数不正确”,我把这几个函数的访问属性GENERIC_READ,WRITE FILE_SHARE_READ,WRITE之类的反复调换,还是不行。也不是磁盘太大,内存不够的问题,后面将D盘换成几十兆的E盘也不行。难不成是内存映射文件只能映射文件,不能像CreateFile,ReadFile一样支持读写分区?不把设备当文件?
下面是代码片段:
HANDLE hDevice = CreateFile(_T("\\\\.\\D:"),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
DebugOutput(GetLastError());
return FALSE;
}
HANDLE hFileMapping = CreateFileMapping(hDevice,NULL,PAGE_READWRITE,0,0,NULL);
DebugOutput(GetLastError()); //一到这句就报错,说参数不正确。
LPBYTE pFileView = (LPBYTE)MapViewOfFile(hFileMapping,FILE_MAP_WRITE,0,0,0);
......
请熟悉大文件处理的各位指点迷津,我哪里出了问题?? 很重要,一定要解决。。
------最佳解决方案--------------------
可能就是行不通,GetFileSize(hDevice,NULL)都不行,何况map
写了一段测试,只有io是成功的
------其他解决方案--------------------
按照MSDN的解释,填0,0的话,系统会自动表示成文件的真实大小吗?
If this parameter and dwMaximumSizeHigh are 0 (zero), the maximum size of the file mapping object is equal to the current size of the file that hFile identifies. 而且试了下,不写00,换成别的数也不行。。
------其他解决方案--------------------
1.确保CreateFile的第一个参数路径正确,且非只读文件,因为后面你的参数是PAGE_READWRITE
2.HANDLE hFileMapping = CreateFileMapping(hDevice,NULL,PAGE_READWRITE,0,0,NULL);
我想写个分区逐扇区扫描的功能,之前使用CreateFile(“\\\\.\\D:”,...),是可以的,后来考虑到用ReadFile,WriteFile效率太差,决定一试内存映射文件。
但问题来了,CreateFile()这一步是成功的,但到了CreateFileMapping()时总报错,用GetLastError()查了下错误码,说是“参数不正确”。
将CreateFile(“\\\\.\\D:”,...)换成某个文件的话,比如CreateFile(“\\\\.\\D:\\aaa.dat”,...),再CreateFileMapping()就是成功的。期间,由于报错说“参数不正确”,我把这几个函数的访问属性GENERIC_READ,WRITE FILE_SHARE_READ,WRITE之类的反复调换,还是不行。也不是磁盘太大,内存不够的问题,后面将D盘换成几十兆的E盘也不行。难不成是内存映射文件只能映射文件,不能像CreateFile,ReadFile一样支持读写分区?不把设备当文件?
下面是代码片段:
HANDLE hDevice = CreateFile(_T("\\\\.\\D:"),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
DebugOutput(GetLastError());
return FALSE;
}
HANDLE hFileMapping = CreateFileMapping(hDevice,NULL,PAGE_READWRITE,0,0,NULL);
DebugOutput(GetLastError()); //一到这句就报错,说参数不正确。
LPBYTE pFileView = (LPBYTE)MapViewOfFile(hFileMapping,FILE_MAP_WRITE,0,0,0);
......
请熟悉大文件处理的各位指点迷津,我哪里出了问题?? 很重要,一定要解决。。
------最佳解决方案--------------------
可能就是行不通,GetFileSize(hDevice,NULL)都不行,何况map
写了一段测试,只有io是成功的
#include <windows.h>
#include <winbase.h>
#include <winioctl.h>
#include <iostream>
using namespace std;
int main(int, char **, char **)
{
HANDLE hDevice = CreateFile("\\\\.\\S:",
GENERIC_READ,FILE_SHARE_READ
------其他解决方案--------------------
FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hDevice== INVALID_HANDLE_VALUE){
cout<<"CreateFile() last error :"<<GetLastError()<<endl;
return 0;
}
if(GetFileType(hDevice)==FILE_TYPE_DISK){
cout<<"disk file type"<<endl;
}
DWORD szHigh=0;
DWORD sz=GetFileSize(hDevice,&szHigh);
if(sz==-1){
cout<<"GetFileSize() last error :"<<GetLastError()<<endl;
}else{
cout<<"LOW:"<<sz<<" HIGH:"<<szHigh<<endl;
}
PARTITION_INFORMATION partition;
DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
&partition, sizeof(partition), &sz,NULL);
cout<<"Partion length:"<<(DWORD)(partition.PartitionLength.QuadPart)<<endl;
HANDLE hFileMapping = CreateFileMapping(hDevice,NULL,PAGE_READONLY,0,512,NULL);
if(hFileMapping==0){
cout<<"CreateFileMapping() last error :"<<GetLastError()<<endl;
CloseHandle(hDevice);
return 0;
}
CloseHandle(hFileMapping);
CloseHandle(hDevice);
return 0;
}
------其他解决方案--------------------
按照MSDN的解释,填0,0的话,系统会自动表示成文件的真实大小吗?
If this parameter and dwMaximumSizeHigh are 0 (zero), the maximum size of the file mapping object is equal to the current size of the file that hFile identifies. 而且试了下,不写00,换成别的数也不行。。
------其他解决方案--------------------
1.确保CreateFile的第一个参数路径正确,且非只读文件,因为后面你的参数是PAGE_READWRITE
2.HANDLE hFileMapping = CreateFileMapping(hDevice,NULL,PAGE_READWRITE,0,0,NULL);