内存段和物理RAM

时间:2015-02-02 13:00:09

标签: memory memory-management operating-system cpu-architecture

进程的内存映射似乎被分段为段(堆栈,堆,bss,数据和文本),

  • 我想知道这些片段只是一个抽象的 过程的便利性和物理RAM只是一个线性阵列 地址或物理RAM也碎片化为这些 段?
  • 此外,如果RAM没有碎片,只是一个线性阵列,那么如何 操作系统是否为流程提供了这些段的抽象?
  • 如果进程的内存映射只是一个线性数组而不是分成段(MMU将虚拟地址转换为物理地址),编程会如何改变?

4 个答案:

答案 0 :(得分:6)

在支持虚拟内存的现代操作系统中,进程的地址空间被划分为这些段。并且通常情况下,进程的地址空间以完全随机方式投射到物理RAM上(具有一些固定的粒度,通常为4K)。彼此相邻的地址空间页不必投影到RAM的相邻物理页中。 RAM的物理页不必保持与进程的地址空间页相同的相对顺序。这一切都意味着在RAM中没有这样的分离,并且不可能存在。

为了优化内存访问,操作系统可能(通常会)尝试将进程地址空间的连续页面映射到RAM中的顺序页面,但这只是一种优化。通常情况下,映射是不可预测的。最重要的是,RAM由系统中的所有进程共享,属于不同进程的RAM页面在RAM中任意交错,这消除了在RAM中具有这种“段”的任何可能性。 RAM中没有特定于流程的排序或分段。 RAM只是虚拟内存机制的缓存。

同样,每个进程都使用自己的虚拟地址空间。这是这些细分可以存在的地方。该进程无法直接访问RAM。该过程甚至不需要知道RAM存在。

答案 1 :(得分:2)

这些段在很大程度上方便了程序加载器和操作系统(尽管它们也为粗粒度保护提供了基础;执行权限可以限制为禁止使用rodata的文本和写入)。 1

物理内存地址空间可能是碎片,但不是为了这些应用程序段。例如,在NUMA系统中,硬件使用特定位来指示哪个节点拥有给定的物理地址可能很方便。

对于使用地址转换的系统,OS可以在某种程度上任意地将段放置在物理内存中。 (使用分段转换,外部碎片可能是一个问题;连续的物理内存地址范围可能不可用,需要昂贵的内存段移动。使用分页转换,外部碎片是不可能的。翻译的优点是需要较少的翻译信息:每个段只需要一个基础并与其他元数据绑定,而一个内存部分通常有两个以上的页面,每个页面都有一个基地址和元数据。)

如果没有地址转换,段的放置必然不那么随意。幸运的是,大多数程序并不关心放置段的特定地址。 (单地址空间操作系统

(请注意,可共享部分位于固定位置可能方便。对于代码,这可用于避免通过全局偏移表进行间接,而无需在程序加载器/动态中进行二进制重写链接器。这也可以减少地址转换开销。)

应用程序级编程通常从这种分段中充分抽象,以使其存在不明显。然而,纯粹的抽象对于物理资源使用的强烈优化(包括执行时间)自然不友好。

此外,编程系统可以选择使用更复杂的数据放置(应用程序员不需要知道实现细节)。例如,使用协同程序可能会鼓励使用仙人掌/意大利面条堆,其中不会出现连续性。类似地,垃圾收集运行时可以提供地址空间的附加划分,不仅用于托儿所,而且用于从非叶对象中分离叶子对象(其没有可收集的存储器的引用)(减少标记/扫描的开销)。提供两个堆栈段也不是特别少见,一个用于未采用地址的数据(或至少固定大小),另一个用于其他数据。


1 在类似Unix的操作系统的平面虚拟地址空间中,这些段的一个传统布局(具有向下增长的堆栈)将文本放置在最低地址,rodata紧接着,紧接在其上方的初始化数据,紧接在其上方的零初始化数据(bss),堆从bss顶部向上增长,并且堆栈从虚拟地址空间的应用程序部分的顶部向下增长。

堆和堆栈相互增长允许每个堆的任意增长(对于使用该地址空间的单个线程!)。此放置还允许程序加载器简单地将程序文件从最低地址开始复制到存储器中,按权限对存储器进行分组,并且有时可以允许单个全局指针处理所有全局/静态数据范围(rodata,data和BSS)。

答案 2 :(得分:2)

  

进程的内存映射显示为段(堆栈,堆,bss,数据和文本)碎片

这是Unix使用的基本映射;其他操作系统使用不同的方案。但是,通常,它们会将进程内存空间拆分为单独的段,以执行代码,堆栈,数据和堆数据。

  

我想知道这些段是否只是抽象的流程,而物理RAM只是一个线性的地址数组,或者物理RAM也被分割成这些段?

取决于。 是的,这些细分市场由操作系统创建和管理,以利于流程。但物理存储器可以排列为线性地址,或存储段,或非连续的RAM块。它由操作系统来管理整个系统内存空间,以便每个进程都可以访问它自己的部分内容。

虚拟内存增加了另一层抽象,因此看起来像线性内存位置的内容实际上映射到RAM的不同页面,可以是物理地址空间中的任何位置。

  

此外,如果RAM不是碎片并且只是一个线性阵列,那么操作系统如何为这些过程提供这些段的抽象?

操作系统通过使用虚拟内存映射硬件来管理所有这些。每个进程都会看到其代码,数据,堆栈和堆段的连续内存区域。但实际上,操作系统将每个段内的页面映射到RAM的物理页面。因此,两个相同的运行进程将看到由连续内存段组成的相同虚拟地址空间,但包含这些段的内存页将映射到完全不同的物理RAM页。

但请记住,物理RAM实际上可能不是一个连续的内存块,但实际上可能会分成多个非相邻块或内存库。操作系统可以通过对流程透明的方式管理所有这些。

  

如果进程的内存映射看起来像一个线性数组而不是分成段,那么编程会如何改变?然后MMU只会将这些虚拟地址转换为物理地址。

MMU始终以这种方式运行,将虚拟内存地址转换为物理内存地址。操作系统为每个进程设置和管理每个段的每个页面的映射。例如,每次进程超过其堆栈分配时,操作系统都会捕获一个段错误,并将另一个页面添加到进程的堆栈段,将虚拟页面映射到从可用内存中选择的物理页面。

虚拟内存还允许操作系统临时将进程页面交换到磁盘,这样所有正在运行的进程占用的虚拟内存总量很容易超过系统的实际物理内存RAM空间。只有当前活动的执行进程才能访问真实的物理RAM页面。

答案 3 :(得分:1)

  

我想知道这些片段是否只是抽象的   便利的过程和物理RAM只是一个线性阵列   地址或物理RAM也被分割成这些段?

这实际上很大程度上取决于架构。一些将具有硬件工具(例如x86的描述符寄存器)以将RAM分成段。其他人只是将这些信息保存在软件中(此过程的操作系统内核信息)。此外,一些段信息与执行完全无关,它们仅用于代码/数据加载(例如重定位段)。

  

此外,如果RAM没有碎片,只是一个线性阵列,那么如何   操作系统为流程提供了这些段的抽象吗?

进程代码从不引用段,他只知道地址,因此操作系统无需抽象。

  

如果内存映射到进程,编程将如何改变   会出现像一个线性数组而不是分成段?   然后MMU只会将这些虚拟地址转换为   物理的

编程不会受到影响。当您使用C编程时,您不能定义任何这些段,并且代码也不会引用这些段。这些细分市场将保持有序的布局,甚至不需要在整个操作系统中保持一致。