wordpress   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了windows – 意外的页面处理(同样,VirtualLock =没有操作?)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

今天早上我偶然发现了一些令人惊讶的页面错误,我没想到它们.是的,我可能不应该担心,但它仍然让我感到奇怪,因为在我的理解中它们不应该发生.并且,如果他们不这样做,我会更好. 应用程序(在WinXP Pro 32位下)使用VirtualAlloc(MEM_RESERVE)保留更大的区域(1GB)地址空间,然后使用VirtualAlloc(MEM_COMMIT)分配中等大块(20-50MB)的内存.这是
今天早上我偶然发现了一些令人惊讶的页面错误,我没想到它们.是的,我可能不应该担心,但它仍然让我感到奇怪,因为在我的理解中它们不应该发生.并且,如果他们不这样做,我会更好.

应用程序(在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可能会再次获得该页面,因此当您触摸原始页面时,您仍会遇到页面错误.

大佬总结

以上是大佬教程为你收集整理的windows – 意外的页面处理(同样,VirtualLock =没有操作?)全部内容,希望文章能够帮你解决windows – 意外的页面处理(同样,VirtualLock =没有操作?)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。