加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows – 意外的页面处理(同样,VirtualLock =没有操作?)

发布时间:2020-12-14 01:55:30 所属栏目:Windows 来源:网络整理
导读:今天早上我偶然发现了一些令人惊讶的页面错误,我没想到它们.是的,我可能不应该担心,但它仍然让我感到奇怪,因为在我的理解中它们不应该发生.并且,如果他们不这样做,我会更好. 应用程序(在WinXP Pro 32位下)使用VirtualAlloc(MEM_RESERVE)保留更大的区域(1GB)
今天早上我偶然发现了一些令人惊讶的页面错误,我没想到它们.是的,我可能不应该担心,但它仍然让我感到奇怪,因为在我的理解中它们不应该发生.并且,如果他们不这样做,我会更好.

应用程序(在WinXP Pro 32位下)使用VirtualAlloc(MEM_RESERVE)保留更大的区域(1GB)地址空间,然后使用VirtualAlloc(MEM_COMMIT)分配中等大块(20-50MB)的内存.这是在工人提前完成的,目的是尽可能少地停止主线程.显然,除非内存区域当前被锁定,否则您无法确保不会发生页面错误,但其中一些肯定是可以容忍的(并且是不可避免的).令人惊讶的是每一页都有错误.总是.

因此,假设系统在分配页面之后只是懒惰地创建页面,这在某种程度上也是有意义的(尽管文档提出了不同的东西).很公平,我的坏.
因此,明显的解决方法是VirtualLock / VirtualUnlock,它强制系统创建这些页面,因为它们必须在VirtualLock返回后存在.令人惊讶的是,仍然每一页都有故障.

所以我写了一个小测试程序,按顺序执行上述所有步骤,在每个步骤之间休息5秒,以排除其他代码中的错误.结果是:

> MEM_RESERVE 1GB —>成功,零CPU,零时间,没有任何反应
> MEM_COMMIT 1 GB —>成功,工作集增加2MB,512页错误(每页用户空间分配8个字节的元数据)
> for(… = 128kB){VirtualLock(128kB); VirtualUnlock(128kB的); } —>成功,没有任何反应
> for(… = 4096)* addr = 0; —> 262144页错误,约0.25秒(内核时间约95%). Process Explorer内的“工作集”和“物理”增加1GB
> VirtualFree —>零CPU,“工作集”和“物理”立即变为* poof *.

我的期望是,由于每个页面都被锁定一次,因此至少在此之后它必须存在.当超出配额时,它当然可以移入和移出WS(只要有足够的RAM可用,只需更改一个引用).然而,执行时间,工作集和物理内存指标似乎都不支持这一点.相反,正如它所看到的那样,每个单个访问页面都是在故障时创建的,即使它之前已被锁定.当然我可以在工作线程中手动触摸每一页,但是必须有更清洁的方法吗?

关于VirtualLock应该做什么,或者我对虚拟内存没有正确理解,我是否做出了错误的假设?任何关于如何以“干净,合法,有效”的方式告诉操作系统我想要记忆的想法,我会想要它真实吗?

更新:
为了回应Harry Johnston的建议,我尝试了一个有问题的方法,实际上在一个GB的内存上调用VirtualLock.为了成功,您必须首先相应地设置进程的工作集大小,因为默认配额是200k / 1M,这意味着VirtualLock不可能锁定大于200k的区域(或者更确切地说,它不能锁定超过200k的区域,并且减去已经锁定的I / O或其他原因)

将最小工作集大小设置为1GB且最大为2GB后,所有页面错误都会在调用VirtualAlloc(MEM_COMMIT)时发生. Process Explorer中的“虚拟大小”立即跳起1GB.到目前为止,它看起来非常非常好.
然而,仔细观察,“物理”仍然保持原样,实际记忆实际上只在您触摸它的那一刻使用.

VirtualLock仍然是一个无操作(故障),但提高最小工作集大小更接近目标.

但是,篡改WS大小有两个问题.首先,你通常不打算在一个进程中拥有一个千兆字节的最小工作集,因为操作系统会努力保持锁定的内存量.这在我的情况下是可以接受的(它实际上或多或少只是我要求的).
更大的问题是SetProcessWorkingSetSize需要PROCESS_SET_QUOTA访问权限,这不是“管理员”的问题,但是当你以受限制的用户运行程序时(由于一个充分的理由)它会失败,并且它会触发“允许可能有害的程序” ?”一些着名的俄罗斯反病毒软件的警报(没有充分的理由,但唉,你不能把它关掉).

解决方法

从技术上讲,VirtualLock是一个提示,因此操作系统可以忽略它.它由NtLockVirtualMemory系统调用支持,它在Reactos / Wine上实现为无操作,但 Windows确实支持系统调用实际工作(MiLockVadRange).

VirtualLock无法保证成功.调用此函数需要SE_LOCK_MEMORY_PRIVILEGE才能工作,并且地址必须满足安全性和配额限制.此外,在VirtualUnlock之后,内核不再需要将页面保留在内存中,因此之后的页面错误是一个有效的操作.

正如Raymond Chen指出的那样,当你解锁内存时,它可以正式释放页面.这意味着下一页上的下一个VirtualLock可能会再次获得该页面,因此当您触摸原始页面时,您仍会遇到页面错误.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读