为什么不能分配一块全局性的用户模式内存空间?

为什么不能分配一块全局性的用户模式内存空间?

作者:BlogUpdater |  时间:2022-05-08 |  浏览:70 |  评论已关闭 条评论

有那么一个偶然时刻,有朋友问起我,有没有一种方法,可以保留一块用户模式下的全局性的内存空间。换句话说,他们是希望分配一块全系统里所有进程都可以访问的一块公用内存块,这里,所有的进程不仅包括现在正在运行的,也包含了将来即将运行的那些进程。

他们这样问的原因大抵在于,他们希望将一些用户模式的内存数据映射到系统的每一个进程中,并且不想自己设计一种共享内存机制来实现这个场景。

显然,这不大可行。为什么显然不行。

好吧,我们这样去思考:如果这种方案可行,会发生什么?”如果它可行,则会发生什么”这个思维方式是一种用来判断一种理论是否可能为真的有效逻辑方法。

如果我们真的允许开发者分配一款全局内存空间,会带来什么结果?

首先,我们并不能确保当你执行内存分配的时候,系统一定就有可用的内存供你分配。
假设,有一个程序在尝试耗尽用户模式地址空间(它可以通过在一个无限循环中调用VirtualAlloc(MEM_RESERVE)函数来实现,因为没有实际的内存被提交,所以,系统不需要实际的2G真实内存)

当执行这个一个程序的时候,系统将没有任何可用的地址空间可供分配,直到这个程序终止运行。所以,即使这种方案在技术层面是可行的,但是也不是十分可靠。你的程序需要面对这种系统可能没有可用内存分配的情景。无论如何,你都需要在程序中编写错误处理代码,所以这种方案并没有实际减少对应的工作量。

第二个原因是,如果这种方案可行,则系统应该会提供一个类似于GlobalVirtualAlloc这样的API函数。那么,很好,我可以写一个简单的程序,在一个循环中不停地调用这个函数,这就可以轻松地耗尽全局虚拟地址空间,并且,更要命的是,我将会以一个非管理员权限运行这个程序。会发生什么呢?

我的一个简单的程序,直接会导致它吃掉所有的全局虚拟地址空间,相应的,这也会减少其他的以管理员权限运行的程序可以分配的地址空间容量。如果系统上运行的程序不多,我的程序可能会通过这种方式占用相当多的地址空间,这反过来会导致这些管理员程序的可用地址空间相应减少。因此,我可以使这些程序更快地耗尽地址空间,从而导致过早失败(DOS, 拒绝服务)。

的确,你可以设计为,全局地址空间仅对管理员程序可用,但这对懒惰的程序员没有帮助,因为该程序在以非管理员身份运行时无法运行——无论如何你都必须编写错误处理代码。

或者,你也可以设计为,全局地址空间仅适用于具有相同安全令牌的同一会话中的用户程序,但同样,如果全局地址分配失败,你仍然必须编写错误处理代码,看起来,这没有为自己节省任何工作。

时机成熟时,你可以使用VirtualAlloc并传递一个首选地址来尝试获取该地址处的内存;如果失败,则会执行你已经编写的错误处理代码。

今天文章的中心思想是:系统中的每一个进程,都拥有它们自己的地址空间,且它们各自对该地址空间的任何操作不会影响到其他进程。
当然,一个例外情况是,一个进程可以授予用户PROCESS_VM_OPERATION权限,该权限授予该用户处理该进程的地址空间的权限。 但是对该进程地址空间的更改不会影响其他进程的地址空间。

总结
你以为你拥有整个世界,他也这样以为。
但是,这年头,凡事都有个但是。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《You cannot globally reserve user-mode address space》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。