这个课题是在项目高文件存取速度的的要求下提出的。WindowsCE支持传统的磁盘文件读写函数,包括MFC封装下的CFile::Read()及CFile::Write()。然而WindowsCE针对一般嵌入式系统,不可能默认系统存在硬盘这样的永久存储体,因此在这些函数的实现上,实际是将数据置于特定内存中,而这还不同于系统对文件读写缓冲区,因此造成了内存频繁操作降低存取速度。
WindowsCE的文件操作应该是基于内存映像的文件存取,即把一个被操作的文件(句柄资源)映射到一块内存区域,而不是一个磁盘文件,这样基于这个内存区域进行读写操作实质上成为对相应的文件的读写。当文件存取作业结束后,系统将内存映射文件按照打开文件的设定参数存入永久存储体中,当然也可指定临时文件而不需存入硬盘,这也是内存映射文件的一大作用。
首先创建所访问文件的句柄,在Win32下采用通用的CreateFile(),而WindowCE下API有专用的创建准备内存映射操作的文件创建接口CreateFileForMapping(),不过有些文章称即使在WIndowCE下也尽量不用后者。
一项目代码为:
HANDLE hFile=CreateFileForMapping(strFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
TRACE(_T("创建文件对象失败,错误代码:%d/r/n"), GetLastError());
return 0;
}
然后创建文件映射对象句柄,并指定文件句柄与之关联:
HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, iFileSize, NULL);
if (hFileMap == INVALID_HANDLE_VALUE)
{
TRACE(_T("创建文件映射对象失败,错误代码:%d/r/n"), GetLastError());
CloseHandle(hFile);
return 0;
}
从内存映像句柄中找到内存访问指针,那么就可以通过该指针进行内存操作:
LPBYTE lpbMapAddress = (LPBYTE) MapViewOfFile ( hFileMap, FILE_MAP_ALL_ACCESS , 0, 0, 0 );
if (lpbMapAddress == NULL)
{
TRACE(_T("映射文件映射失败,错误代码:%d/r/n"), GetLastError());
CloseHandle(hFileMap);
CloseHandle(hFile);
return 0;
}
return lpbMapAddress;
例如对文件的写操作可以为:
memcpy(lpbMapAddress, pDataBuffer,iByteNumberToWrite);
文件作业结束后,释放相应资源,系统将把内存数据写入对应文件中:
UnmapViewOfFile(lpbMapAddress);
CloseHandle(hFileMap);
CloseHandle(hFile);
在使用内存映射文件具体编程中,应注意文件的大小,文件与对应内存映射的读写权限一直等问题。
在ARM9-EP9315片上系统部署Window CE4.2系统,以1G Flash为永久存储体,进行两者操作速率测试。实验结果是,在同样文件条件下,采用内存映射方式进行文件存储操作时间是采用CFile进行文件操作时间的1/3,从而提高了嵌入式软件文件操作速率。
(文中全部代码取自真实项目,于Microsoft Embedded Visual C++环境编译通过,在ARM9+Windows CE4.2环境下运行正确稳定)