RAM如何分配?

这是关于计算机科学的一个小问题:ram如何分配?

例如,我使用Windows。 我可以知道一个程序使用哪个地址吗? Windows如何分配内存? 连续的还是不连续的? 在Linux操作系统上它是一样的吗?

而且,我可以通过程序访问整个公羊吗? (我不相信,但是…)

你知道这个有什么好的讲座/文档吗?

首先,当你认为你正在分配内存,你真的不是 。 这是令人困惑的,我知道,但是一旦你明白它是如何工作的,这并不复杂。 继续阅读。

RAM由操作系统以称为“页面”的单位分配。 通常,这意味着4kiB的连续区域,但其他大小是可能的(使事情进一步复杂化,在现代处理器上支持“大页面”(通常大约1-4MiB),并且操作系统可能具有分配粒度与页面大小不同,例如Windows的页面大小为4kiB,粒度为64kB)。
让我们忽略这些额外的细节,只是想到具有特定大小(4KiB)的“页面”。

如果您分配和使用的区域大于系统的页面大小,则通常不会有连续的内存,但您仍然会将其视为连续的,因为您的程序只能在虚拟地址中“思考”。 实际上,您可能会使用两个(或更多)不是连续的页面,但它们似乎是。 这些虚拟地址被MMU透明地转换为实际的地址。
另外,并不是所有你认为已经分配的内存都必须始终存在于RAM中,并且相同的虚拟地址可能在不同的时间对应于完全不同的RAM块(例如当页被换出并且随后再次被换入 – 你的程序会在同一个地址看到它,但实际上很可能是在不同的RAM中)。

虚拟内存是一个非常强大的工具。 虽然程序中的一个地址只能指向RAM中的一个物理地址(在一个特定的页面中),但是RAM的一个物理页面可以被映射到程序中的几个不同的地址,甚至在几个独立的程序中。
例如,创建“循环”内存区域是可能的,而共享库中的代码通常被加载到一个内存位置,但被许多程序同时使用(并且在这些不同的程序中将具有不同的地址)。 或者,你可以用这种技术在程序之间共享内存,所以当一个程序写入某个地址时,另一个程序的内存位置的值会改变(因为它是完全相同的内存!)。

在高层次上,你问你的标准库的内存(如malloc ),标准库管理一个或多或少没有指定的方式保留的区域池(有许多不同的分配器实现,它们都有共同点你可以问他们的记忆,他们给回地址 – 这是你认为你分配内存时,你不在)。
当分配器需要更多的内存时,它会要求操作系统保留另一个块。 在Linux下,这可能是sbrkmmap ,在Windows下,这可能是VirtualAlloc

通常情况下,可以使用内存做3件事情,在Linux和Windows(以及其他所有的现代操作系统)下,它们通常都是一样的,尽管使用的API函数是不同的,还有一些细微的差别。

你可以保留它,除了在逻辑上划分你的地址空间(只有你的进程在意这个)之外,这或多或少没有任何意义。
接下来,你可以提交它,这不会有太大的作用,但它会影响其他进程。 系统对所有进程(物理内存和页面文件大小)可以提交多少内存进行了总计限制,并且跟踪了这一点。 这意味着您提交的内存数量与另一个进程可能提交的数量相同。 否则,再次,没有太多的事情发生。
最后,你可以访问内存。 最后这个效果明显。 在第一次访问页面时,会发生错误(因为页面根本不存在!),操作系统从文件中获取一些数据(如果页面属于一个映射)或者清除某个页面(可能在第一个页面之后保存到磁盘)。 OS然后调整虚拟内存系统中的结构,以便在您访问的地址处看到RAM的物理页面。

从你的角度来看,没有一个是可见的。 它就像魔术一样工作。

可以检查地址空间中哪些区域被使用的过程,并且可能(但没有意义)将其转换为物理地址。 请注意,在不同时间运行相同的程序可能会在一个不同的地址存储例如一个特定的变量。 在Windows下,您可以使用VMMap工具来检查进程内存分配。

如果您编写自己的操作系统,则只能使用所有的RAM,因为操作系统会保留一些用户进程无法使用的内存。
否则,你原则上可以使用[几乎]所有的内存。 但是,你是否可以直接使用这个取决于你的进程是32位还是64位。 现在的计算机通常具有比32位更多的内存,所以无论是需要使用地址窗口扩展还是处理过程必须是64位。 而且,即使给定的RAM数量原则上可以使用32位进行寻址,一些地址空间因素(例如,fragentation,内核预留)可能会阻止您直接使用所有内存。

这是一个重要的问题。

RAM是按程序需要分配的。 一些语言,比如C或者C ++,会让你自己做这个。 其他的,如Java,将为您提供可爱的抽象分配内存。

我们分配内存是因为我们想存储一些东西。 RAM是变量等被存储为电子二进制信号的文字。

是的,很有可能知道程序使用了哪些地址。 我相信有一些工具可以做到这一点。 如果你正在编写C ++,你可以创建一个指向空闲存储(一大块内存)地址的指针: int * i = new int; 。 如果你想知道它存储在哪里,你只需要std::cout << "int i is at " << i << "." << endl; std::cout << "int i is at " << i << "." << endl;

我不知道什么是连续的和不连续的(对不起,懒惰),但是一个快速的搜索表明Windows是连续的,而GNU / Linux不是。 在所有抽象的基础上,大多数Windows内存在免费存储上,并包含对象或数据结构。

是的,你可以通过程序访问(我相信)整个RAM。 这听起来很糟糕,但你所要做的就是自己改变指针地址,例如i ++; (实际上是遍历数组的相当常见的操作)。

我没有回顾这些,但这些视频似乎相当可信:

  • C ++基本技能:第14课“动态内存分配”(第1部分,共2部分)

  • 动态内存分配在C – malloc calloc realloc free

  • 有关Java内存分配的更多YouTube视频