I finally found the way, derived from a thread here. The trick is using VirtualUnlock() on the ranges I need to uncommit; although this function returns FALSE with error 0x9e ("The segment is already unlocked"), memory is actually released, even if the pages were modified (file is correctly updated).
Here's my sample test program:
#include "stdafx.h"
void getenter(void)
{
int ch;
for(;;)
{
ch = getch();
if( ch == '
' || ch == '
' ) 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
", 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
", 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
", GetLastError() );
getenter();
CloseHandle(map_handle);
CloseHandle(hfile);
return 1;
}
// Memory usage here is 704KB
printf("Mapped.
"); getenter();
for( int n = 0 ; n < 10000 ; n++ )
{
map_ptr[n*4096]++;
}
// Memory usage here is ~40MB
printf("Used.
"); getenter();
if( !VirtualUnlock( map_ptr, 5000 * 4096 ) )
{
// Memory usage here is ~20MB
// 20MB already freed!
fprintf( stderr, "VirtualUnlock() error 0x%08x
", GetLastError() );
getenter();
UnmapViewOfFile(map_ptr);
CloseHandle(map_handle);
CloseHandle(hfile);
return 1;
}
// Code never reached
printf("VirtualUnlock() executed.
"); getenter();
UnmapViewOfFile(map_ptr);
CloseHandle(map_handle);
CloseHandle(hfile);
printf("Unmapped and closed.
"); getenter();
return 0;
}
As you can see, the working set of the program is reduced after executing VirtualUnlock(), just as I needed. I only need to keep track of the pages I change in order to unlock as appropriate.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…