CreateFileMapping,MapViewOfFile,如何避免阻塞系统内存

我正在开发针对桌面系统的应用程序,它可能只有256MB RAM(Windows 2000以上)。 在我的应用程序中,我有这个大文件(> 256MB),其中包含约160字节/每个的固定logging。 这个应用程序有一个相当漫长的过程,随着时间的推移,它将随机访问大约90%的文件(用于阅读和写作)。 任何给定的logging写入不会超过特定logging的读取次数(我可以调整该值)超过1,000条logging。

我有两个明显的select这个过程:常规I / O(FileRead,FileWrite)和内存映射(CreateFileMapping,MapViewOfFile)。 后者应该在有足够内存的系统中效率更高,但是在内存不足的系统中,它会将大部分其他应用程序的内存换掉,这在我的应用程序中是不可能的。 有没有办法阻止进程消耗所有的内存(例如,强迫刷新我不再访问的内存页面)? 如果这是不可能的,那么我必须诉诸于正常的I / O; 我希望在写作部分使用重叠的I / O(因为访问是随机的),但是文档说less于64K的写入总是同步服务 。

任何改进I / O的想法都是受欢迎的。

Solutions Collecting From Web of "CreateFileMapping,MapViewOfFile,如何避免阻塞系统内存"

我终于找到了方法,从这里得到一个线程。 诀窍是在我需要取消提交的范围上使用VirtualUnlock(); 虽然此函数返回FALSE错误0x9e(“该段已被解锁”),内存实际上被释放,即使页面被修改(文件被正确更新)。

这是我的示例测试程序:

#include "stdafx.h" void getenter(void) { int ch; for(;;) { ch = getch(); if( ch == '\n' || ch == '\r' ) return; } } int main(int argc, char* argv[]) { char* fname = "c:\\temp\\MMFTest\\TestFile.rar"; // 54 MB HANDLE hfile = CreateFile( fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if( hfile == INVALID_HANDLE_VALUE ) { fprintf( stderr, "CreateFile() error 0x%08x\n", GetLastError() ); getenter(); return 1; } HANDLE map_handle = CreateFileMapping( hfile, NULL, PAGE_READWRITE | SEC_RESERVE, 0, 0, 0); if( map_handle == NULL ) { fprintf( stderr, "CreateFileMapping() error 0x%08x\n", GetLastError() ); getenter(); CloseHandle(hfile); return 1; } char* map_ptr = (char*) MapViewOfFile( map_handle, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ); if( map_ptr == NULL ) { fprintf( stderr, "MapViewOfFile() error 0x%08x\n", GetLastError() ); getenter(); CloseHandle(map_handle); CloseHandle(hfile); return 1; } // Memory usage here is 704KB printf("Mapped.\n"); getenter(); for( int n = 0 ; n < 10000 ; n++ ) { map_ptr[n*4096]++; } // Memory usage here is ~40MB printf("Used.\n"); getenter(); if( !VirtualUnlock( map_ptr, 5000 * 4096 ) ) { // Memory usage here is ~20MB // 20MB already freed! fprintf( stderr, "VirtualUnlock() error 0x%08x\n", GetLastError() ); getenter(); UnmapViewOfFile(map_ptr); CloseHandle(map_handle); CloseHandle(hfile); return 1; } // Code never reached printf("VirtualUnlock() executed.\n"); getenter(); UnmapViewOfFile(map_ptr); CloseHandle(map_handle); CloseHandle(hfile); printf("Unmapped and closed.\n"); getenter(); return 0; } 

正如你所看到的,执行VirtualUnlock()之后,程序的工作集合就会减少,就像我需要的一样。 我只需要跟踪我改变的页面,以便适当解锁。

只需将整个文件映射到内存。 这消耗虚拟但不是物理内存。 该文件是从磁盘分段读取的,并由管理交换文件的相同策略从内存中逐出。

VirtualUnlock似乎不起作用。 你需要做的就是在UnmapViewOfFile(map_ptr)之前立即调用FlushViewOfFile(map_ptr,0)。 Windows任务管理器不会显示物理内存使用情况。 从SysInternals使用ProcessExplorer

你是否用MapViewOfFile将整个文件映射为一个块? 如果你是,尝试映射较小的部分。 您可以使用FlushViewOfFile()刷新视图