是否有可能在Windows中卸载所有内存?

我有大量的内存,但是,在启动并完成大量进程之后,似乎大多数应用程序的虚拟内存已经被分页到磁盘,并且切换到任何较旧的进程需要很长时间来加载内存回到RAM中。

有没有办法,无论是通过Windows API或通过内核调用,让Windows无法全部(或尽可能)的内存? 也许通过逐步通过正在运行的进程列表并获取内存pipe理器来卸载每个进程的内存?

Solutions Collecting From Web of "是否有可能在Windows中卸载所有内存?"

那么,实现你自己并不难。 使用VirtualQueryEx()来发现进程使用的虚拟地址, ReadProcessMemory()强制页面重新加载。

根本不可能有任何改变,只是你的程序需要永远做的工作。 缓慢重新加载页面的常见诊断是分段的分页文件。 在Windows XP上是常见的,例如当磁盘长时间没有被整理,并且允许频繁地填充容量。 SysInternals的PageDefrag实用程序可以帮助解决这个问题。

更新3:我已经把我的完整程序上传到github 。


好的,根据迄今为止的回复,这是一个天真的建议,试图将所有的应用程序回到物理内存的工具:

  1. 分配一小块内存X,大概是4MB。 (它应该是不可分页的?)
  2. 遍历所有进程:
    • 对于每个进程,将其内存复制到X.(可能首先暂停进程?)

假设你有2GB的内存,进程实际只需要1GB的内存。 如果一切都在物理内存中,你只能复制256块,而不是世界的尽头。 在一天结束的时候,所有进程现在完全存在于物理内存中的可能性很大。

可能的便利和优化选项:

  • 首先检查所需的总空间不超过总物理空间的50%。
  • 也可以只在当前用户拥有的进程上或用户指定的列表上运行。
  • 首先检查每块内存是否实际分页到磁盘。

我可以使用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); } 

问题:我增加的区域最多只有一个页面,还是缺少页面? 我是否应该尝试找出页面大小,并且只增加区域大小和页面大小的最小值? 更新2:页面大小只有4kiB! 我改变了上面的代码只能以4kiB的步骤递增。 在最后的代码中,我们摆脱了循环内部的fprintf。

不,Windows本身不提供这样的功能。 像Cacheman和RAM IDLE这样的程序通过简单地分配一大块内存来实现这一点,强制其他东西去寻呼到磁盘,这就有效地完成了你想要的任务。