我正试图在操作系统级别围绕Windows内存管理的内部。
在分配内存时,它总是在幕后触发页面错误吗?这是否意味着停止软页面错误的唯一方法是停止在进程中分配新内存?
解释
我将“内存分配”定义为任何形式的malloc,即new,LocalAlloc,VirtualAlloc,HeapAlloc等。
我将“页面错误”定义为将内存从操作系统池映射到进程工作集的过程,该操作在高端Xeon上持续250us。
答案 0 :(得分:8)
你需要非常清楚这里发生的不同事情。进程有两个独立的部分,提交内存并将内存分页到进程中。这些都与调用malloc
,HeapAlloc
或LocalAlloc
无关。
我试图在下面为你打破这个过程,但总结是如果你使用HeapAlloc
或其他等效函数,那么你将触发很少的页面错误(至少一次你的应用程序有初始化并且堆已经增长到稳定的大小)因此不应该担心它太多。
分配内存
当你调用malloc
,HeapAlloc
或LocalAlloc
时,内存分配器将尝试在堆中找到一块可用且足够大的内存。在大多数情况下,它会成功并将记忆归还给你。
如果找不到足够的内存,它会通过调用VirtualAlloc
来分配更多内容(在Linux上,这将是sbrk
或mmap
)。此提交内存。它将为您返回一小段新内存。
记忆承诺
当您或分配器呼叫VirtualAlloc
时,这将标记虚拟内存的新区域为可访问。这不会触发页面错误,也不会实际为这些页面分配物理内存。来自VirtualAlloc的MSDN文档:
分配内存费用(来自内存的整体大小和磁盘上的分页文件) 对于指定的保留内存页面。该函数还保证了当调用者 后来最初访问内存,内容将为零。实际的物理页面是 除非/直到实际访问虚拟地址,否则不会分配。
中的内存分页
当您第一次访问VirtualAlloc
已返回给您的内存页面时,会触发软页面错误。操作系统将找到一页空闲物理内存,将其归零并将其分配给您访问的虚拟页面。这对您来说是透明的,只需要很少的时间(一位数的微秒)。如果您停止使用它,操作系统可能会将此内存交换到磁盘,这是合理的,如果确实如此,则后续访问将触发硬页面错误。
答案 1 :(得分:1)
嗯,是的,页面错误会使CPU重新进入内核模式,内核有机会了解用户空间进程需要某个内存页面。然后,内核可以查询其内部存储器管理簿记数据,使适当大面积的物理内存可用,并调整处理器的页表,以便映射所请求的虚拟地址。完成后,执行会返回到用户空间进程,该进程会在成功分配后恢复。
这不应与意外页面错误相混淆,通过该错误,用户空间进程引用既未映射到页面表也未知的地址。内核的内存管理器属于该进程。在这种情况下,内核将杀死流氓进程。