原则上可以通过进程释放内存页吗?

原则上可以通过进程释放内存页吗?

免责声明:我确实拥有计算机科学文凭,但从未向我明确解释过这个主题。我只是将我所知道的碎片拼接成一个整体。如果我有什么不对的地方,请纠正我。

假设您有一个 C 程序:您调用malloc(1MB).该函数不会从操作系统分配任何内存页。它所做的只是使用堆从虚拟内存地址空间分配一系列地址。这些地址尚未映射到任何实际内存页面。第一次写入该地址时,CPU 捕获异常(或中断等)并将新的内存页分配给该地址,然后写入成功。

然后我调用该free()函数。此函数也不会将任何内存页释放回操作系统。它所做的只是将地址范围放回堆中以供将来重用。

我的观点是,内存页永远不会被释放(直到进程终止)。是对的吗?没有用于释放内存页面的系统调用,是吗?并且操作系统本身无法猜测哪些页面不再使用。它所能做的就是查看哪些页面是最近最少使用的,并将这些页面移至交换位置。

相关(有点)问题:是否可以强制应用程序释放一些分配的内存? 还相关:https://stackoverflow.com/questions/1421491/does-calling-free-or-delete-ever-release-memory-back-to-the-system

答案1

原则上和实践中释放页面都是可能的。

malloc并且free不一定会导致保留地址空间;它们可以使用mmap和来实现munmap,在这种情况下,相应的地址空间和任何填充的页面都可以在 后返回到内核munmap。进程还可以使用 来减少分配的地址空间sbrk

madvise函数也可用于丢弃页面,而不释放地址空间。

答案2

最后,操作系统内核是否允许零碎地“归还”(虚拟内存)页面(这样做可能会很混乱;并且在实践中并不相关,未使用的页面将无论如何,很快就会被从 RAM 中驱逐)。出于或多或少相同的原因,语言的运行时可能只是保留一些东西(如果你例如在 C go 和 中malloc()free()没有什么可以保证你释放的空间是地址空间中的连续页面 - 将其归还只是为了要求更多稍后的空间有其成本)。

Unix 有sbrk(2),它允许扩展/收缩进程的数据段,但是假设有数据段(最终可能有几个),运行时堆栈原则上会扩展和收缩。同样,如果语言的运行时或内核对此起作用,则取决于实现。

例如,检查 C 的标准:他们仔细地表述了“好像”规则,程序必须通过抽象出任何此类细节并处理任何资源限制来以可解释的方式运行。

相关内容