程序从哪里分配内存?

作为C和C ++程序员,我使用mallocnew来分配内存。 我只是想知道:操作系统如何分配内存?

  1. 它是从RAM还是从硬盘或其他地方分配的?

  2. 为了以防万一,我可以从硬盘借内存吗?

它实际上比你想象的要复杂得多。 操作系统会考虑“页面”中的所有内容,将RAM拆分为页面,将硬盘拆分为页面。 当您的程序启动时,它会检查您的可执行文件占用多少内存,为它选择一些RAM页面,并将这些页面分配给您的程序。 如果RAM中没有“可用”页面,它会占用RAM中较旧的一些页面,并将它们保存到隐藏在某处的硬盘驱动器中,然后将这些页面提供给您。

在程序中分配内存时,程序的内存管理器将尝试在操作系统分配给它的页面中找到一个空闲位置。 如果还不够,它会向操作系统询问更多页面,并且操作系统会腾出更多空间并为您的应用程序提供更多页面。

如果您的程序有一段时间没有使用的页面(有时甚至是代码),操作系统可能会将该页面保存到硬盘驱动器,当程序再次尝试使用该页面时,操作系统会暂停您的程序程序,将页面重新加载到RAM中,然后恢复您的程序。

这是一个毫无意义的图表

 C++ addresses RAM hard drive +------------+ +------------+ +------------+ | 0x00010000 |\ ->| 0x00010000 | | 0x00010000 | +------------+ X +------------+ +------------+ | 0x00020000 |/ ->| 0x00020000 | | 0x00020000 | +------------+ +------------+ +------------+ | 0x00030000 |-->? /----->| 0x00030000 | +------------+ / +------------+ | 0x00040000 |-----------/ | 0x00040000 | +------------+ | etc | 

所以在这段代码中,你的代码的堆栈内存为0x00010000-0x0002FFFF,你已经分配了一些动态内存,那就是0x0004000。 就像你知道的那样! 实际上,当您访问0x0002000时,操作系统会说“哦,我已将您的那个页面存储在RAM地址0x00010000”中并为您读取这些值。 你有一段时间没有触及0x00040000的页面,所以操作系统将它保存到硬盘驱动器位置0x00030000的硬盘驱动器上,但如果你试图使用它,它会把它带到RAM中。 操作系统尚未提供地址0x00030000,因此如果您尝试使用它,操作系统会告诉您该地址没有任何实际页面,并且您会收到分段错误(segfault)。 让这个有趣的是当你要求一个像矢量这样的大型连续块时,操作系统可以给你发现它周围的任何旧页面,它不必担心它们是否是连续的。 它们看起来与您的程序相邻,这一切都很重要。

这也允许操作系统隐藏一个程序的存储器,使其无法读取或修改其他程序的存储空间。 他们很安全! 除了……有办法告诉操作系统在两个程序之间共享页面(尽管它们在每个程序中可能有不同的地址),允许它们共享页面。 DLL这样做。

实际上,它比这复杂得多。

1)它是从RAM还是从硬盘或其他地方分配的?

在支持虚拟内存的现代系统/平台上,操作系统决定在何处以及如何分配/存储内存。 系统也可以自由地将内存从一个地方移动到另一个地方,无论是在RAM还是在磁盘上。

2)为了以防万一,我可以从硬盘借内存吗?

管理内存的操作系统可以从磁盘中借用内存。

您还可以通过将数据存储在文件中来明确地从磁盘中借用内存。 C和C ++标准库( stdio.hfstream )支持文件操作。

当您解决由malloc或operator new分配的malloc ,它位于RAM中并具有唯一的地址。 操作系统的工作是在寻址时在RAM中占用该块内存,但它可以自行决定将其交换到磁盘。 由于交换速度很慢,因此要由操作系统来确定如何最小化交换。

使用“虚拟内存”的操作系统允许您设置虚拟内存管理器可用的磁盘空间量。

虽然您可能会考虑使用数据库来管理数据是否更好,尤其是在数据的生命周期长于单个会话时,您无需自己尝试自行管理。

这个答案将以Linux为中心

它看起来要复杂得多。 分配内存块时,可能会发生以下两种情况之一。 如果您的进程已经有足够的内存以前已释放但未返回到操作系统(分配器通常不会),则该内存将在分配器表中标记为已分配,并将返回。 当进程还没有内存时,分配器会向操作系统询问更多内存。 在Linux上,这意味着brksbrk系统调用。 我不知道它在Windows或OSX上意味着什么。

所有现代的常见操作系统(Linux,Windows,OSX及其衍生产品)都使用虚拟内存,地址的概念不一定指向真正的RAM。 在你输入内容之前,你分配的内存可能根本不存在。 一旦开始使用它,操作系统需要在RAM中为它腾出空间。 为此,操作系统会将其他未使用的页面(部分内存)存储在磁盘上的交换文件或分区中(如果已配置)。

操作系统不断地在交换存储和实际RAM之间移入和移出内存页。 每当您的进程访问当前不在RAM中的内存部分时,处理器会生成页面错误,导致操作系统从磁盘加载该页面,并通过移动其他页面为内存腾出空间交换。


所以基本上,在现代操作系统中,内存可以来自操作系统选择的任何地方,甚至可能在您分配时也不存在


注意:有些操作系统,比如Linux大多数时候,甚至会让你分配它没有给你的内存。 这称为过度使用内存。