我有足够的RAM,但是,在启动和完成大量进程后,似乎大多数应用程序的虚拟内存已被分页到磁盘,并且切换到任何较旧的进程需要很长时间才能加载内存回到RAM.
有没有办法,通过Windows API或通过内核调用,让Windows取消所有(或尽可能多)内存?也许通过逐步运行进程列表并让内存管理器取消每个进程的内存?
Ker*_* SB 10
更新3:我已将我的完整程序上传到github.
好的,基于到目前为止的回复,这里有一个天真的建议,试图让所有应用程序回到物理内存:
假设你有2GB的RAM,进程实际上只需要1GB.如果一切都在物理内存中,那么你只能复制256个块,而不是世界末日.在一天结束时,所有进程现在完全在物理内存中的可能性很大.
可能的便利和优化选项:
我可以使用EnumProcesses()迭代所有进程; 如果有任何建议如何复制整个进程的内存块,我将不胜感激.
更新:这是我的示例功能.它将进程ID作为其参数,并从进程的每个良好页面复制一个字节.(第二个参数是最大进程内存大小,可通过GetSystemInfo()获得.)
void UnpageProcessByID(DWORD processID, LPVOID MaximumApplicationAddress, DWORD PageSize)
{
MEMORY_BASIC_INFORMATION meminfo;
LPVOID lpMem = NULL;
// Get a handle to the process.
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
// Do the work
if (NULL == hProcess )
{
fprintf(stderr, "Could not get process handle, skipping requested process ID %u.\n", processID);
}
else
{
SIZE_T nbytes;
unsigned char buf;
while (lpMem < MaximumApplicationAddress)
{
unsigned int stepsize = PageSize;
if (!VirtualQueryEx(hProcess, lpMem, &meminfo, sizeof(meminfo)))
{
fprintf(stderr, "Error during VirtualQueryEx(), skipping process ID (error code %u, PID %u).\n", GetLastError(), processID);
break;
}
if (meminfo.RegionSize < stepsize) stepsize = meminfo.RegionSize;
switch(meminfo.State)
{
case MEM_COMMIT:
// This next line should be disabled in the final code
fprintf(stderr, "Page at 0x%08X: Good, unpaging.\n", lpMem);
if (0 == ReadProcessMemory(hProcess, lpMem, (LPVOID)&buf, 1, &nbytes))
fprintf(stderr, "Failed to read one byte from 0x%X, error %u (%u bytes read).\n", lpMem, GetLastError(), nbytes);
else
// This next line should be disabled in the final code
fprintf(stderr, "Read %u byte(s) successfully from 0x%X (byte was: 0x%X).\n", nbytes, lpMem, buf);
break;
case MEM_FREE:
fprintf(stderr, "Page at 0x%08X: Free (unused), skipping.\n", lpMem);
stepsize = meminfo.RegionSize;
break;
case MEM_RESERVE:
fprintf(stderr, "Page at 0x%08X: Reserved, skipping.\n", lpMem);
stepsize = meminfo.RegionSize;
break;
default:
fprintf(stderr, "Page at 0x%08X: Unknown state, panic!\n", lpMem);
}
//lpMem = (LPVOID)((DWORD)meminfo.BaseAddress + (DWORD)meminfo.RegionSize);
lpMem += stepsize;
}
}
CloseHandle(hProcess);
}
Run Code Online (Sandbox Code Playgroud)
问题:我增加大小的区域最多只包含一页,还是我缺少页面?我是否应该尝试找出页面大小,并且只增加区域大小和页面大小的最小值? 更新2:页面大小只有4kiB!我改变了上面的代码只在4kiB步骤中增加.在最终的代码中,我们将摆脱循环中的fprintf.
嗯,实现自己并不困难.使用VirtualQueryEx()
发现一个进程使用的虚拟地址,ReadProcessMemory()
以武力得到重新加载页面.
它根本不可能产生任何差别,它只是你的程序需要永远完成它的工作.缓慢重新加载页面的常见诊断是分段的页面文件.在Windows XP上常见,例如,磁盘在很长一段时间内没有进行碎片整理,并且允许频繁填充接近容量.SysInternals的PageDefrag实用程序可以帮助解决问题.
归档时间: |
|
查看次数: |
1340 次 |
最近记录: |