Linux 操作系统通常允许内存过度使用。例如,即使计算机只有 8GB 物理内存且没有交换区,进程也可以分配 100GB 内存。
只要分配的内存没有被实际使用,进程就会运行。如果程序试图使用全部内存,OOM-killer 就会终止进程以释放内存。
这在 Windows 中如何工作?除非 Windows 能够保证该内存可以由实际内存(物理 RAM 或交换)支持,否则 Windows 是否会拒绝为进程提供虚拟内存?
答案1
回答我自己的问题,因为没有其他人回答过。
看起来 Windows 不会过度使用内存。这实际上与 Linux 有很大不同。
Windows 将允许程序分配比机器上的 RAM 更多的(虚拟)内存,但前提是有足够的可用磁盘空间能够在必要时通过磁盘支持程序请求的虚拟内存。
答案2
不确定这是否相关,但某些应用程序的内存使用会受到限制,例如 Powershell,除非更改内存分配设置,否则会抛出这些错误。或者你通过单独的应用程序运行命令,例如 Spyder。
答案3
Windows 确实会过度省略堆栈。您可以轻松创建大量线程,其堆栈空间远远超过 RAM + 交换空间。以下 C++20 程序显示了 1 MB 堆栈的页面属性:
#include <Windows.h>
#include <iostream>
using namespace std;
int main( int argc, char **argv )
{
auto stackThread = []( LPVOID lpvThreadParam ) -> DWORD
{
ULONG_PTR stackTop, stackBottom;
GetCurrentThreadStackLimits( &stackBottom, &stackTop );
char const
*pStackTop = (char *)stackTop,
*pStackBottom = (char *)stackBottom;
SYSTEM_INFO si;
GetSystemInfo( &si );
MEMORY_BASIC_INFORMATION mbi;
auto query = [&]( char const *p ) -> char const *
{
if( VirtualQuery( p, &mbi, sizeof mbi ) != sizeof mbi )
ExitProcess( EXIT_FAILURE );
return (char *)mbi.AllocationBase;
};
char const *base = query( pStackBottom ), *p;
do
{
cout << mbi.RegionSize / si.dwPageSize << ": ";
unsigned n = 0;
auto append = [&]<typename ... T>( T &&... values ) { cout << (", " + !n++); ((cout << values), ...); };
if( mbi.State != MEM_FREE )
if( mbi.State == MEM_COMMIT )
append( "comitted" );
else if( mbi.State == MEM_RESERVE )
append( "reserved" );
else
append( "S: 0x", hex, mbi.State );
if( !mbi.Protect )
append( "unacessible" );
else if( mbi.Protect & PAGE_GUARD )
append( "guard page" );
else if( mbi.Protect == PAGE_READWRITE )
append( "read-write" );
else
append( "P: 0x", hex, mbi.Protect );
cout << endl;
p = (char *)mbi.BaseAddress + mbi.RegionSize;
} while( query( p ) == base && mbi.BaseAddress < pStackTop );
return 123;
};
HANDLE hThread = CreateThread( nullptr, 0x100000, stackThread, nullptr, STACK_SIZE_PARAM_IS_A_RESERVATION, nullptr);
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
return 0;
}
这是我的计算机上显示的堆栈属性:
251: reserved, unacessible
2: comitted, guard page
3: comitted, read-write
如您所见,大部分堆栈最初都是未提交的。