windows – 意外的页面处理(同样,VirtualLock =没有操作?)
今天早上我偶然发现了一些令人惊讶的页面错误,我没想到它们.是的,我可能不应该担心,但它仍然让我感到奇怪,因为在我的理解中它们不应该发生.并且,如果他们不这样做,我会更好.
应用程序(在WinXP Pro 32位下)使用VirtualAlloc(MEM_RESERVE)保留更大的区域(1GB)地址空间,然后使用VirtualAlloc(MEM_COMMIT)分配中等大块(20-50MB)的内存.这是在工人提前完成的,目的是尽可能少地停止主线程.显然,除非内存区域当前被锁定,否则您无法确保不会发生页面错误,但其中一些肯定是可以容忍的(并且是不可避免的).令人惊讶的是每一页都有错误.总是. 因此,假设系统在分配页面之后只是懒惰地创建页面,这在某种程度上也是有意义的(尽管文档提出了不同的东西).很公平,我的坏. 所以我写了一个小测试程序,按顺序执行上述所有步骤,在每个步骤之间休息5秒,以排除其他代码中的错误.结果是: > MEM_RESERVE 1GB —>成功,零CPU,零时间,没有任何反应 我的期望是,由于每个页面都被锁定一次,因此至少在此之后它必须存在.当超出配额时,它当然可以移入和移出WS(只要有足够的RAM可用,只需更改一个引用).然而,执行时间,工作集和物理内存指标似乎都不支持这一点.相反,正如它所看到的那样,每个单个访问页面都是在故障时创建的,即使它之前已被锁定.当然我可以在工作线程中手动触摸每一页,但是必须有更清洁的方法吗? 关于VirtualLock应该做什么,或者我对虚拟内存没有正确理解,我是否做出了错误的假设?任何关于如何以“干净,合法,有效”的方式告诉操作系统我想要记忆的想法,我会想要它真实吗? 更新: 将最小工作集大小设置为1GB且最大为2GB后,所有页面错误都会在调用VirtualAlloc(MEM_COMMIT)时发生. Process Explorer中的“虚拟大小”立即跳起1GB.到目前为止,它看起来非常非常好. VirtualLock仍然是一个无操作(故障),但提高最小工作集大小更接近目标. 但是,篡改WS大小有两个问题.首先,你通常不打算在一个进程中拥有一个千兆字节的最小工作集,因为操作系统会努力保持锁定的内存量.这在我的情况下是可以接受的(它实际上或多或少只是我要求的). 解决方法
从技术上讲,VirtualLock是一个提示,因此操作系统可以忽略它.它由NtLockVirtualMemory系统调用支持,它在Reactos / Wine上实现为无操作,但
Windows确实支持系统调用实际工作(MiLockVadRange).
VirtualLock无法保证成功.调用此函数需要SE_LOCK_MEMORY_PRIVILEGE才能工作,并且地址必须满足安全性和配额限制.此外,在VirtualUnlock之后,内核不再需要将页面保留在内存中,因此之后的页面错误是一个有效的操作. 正如Raymond Chen指出的那样,当你解锁内存时,它可以正式释放页面.这意味着下一页上的下一个VirtualLock可能会再次获得该页面,因此当您触摸原始页面时,您仍会遇到页面错误. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |