内存段和物理RAM
一个进程的内存映射似乎被分割成段(堆栈,堆,bss,数据和文本),
在支持虚拟内存的现代操作系统中,被分为这些段的进程的地址空间。 在一般情况下,该进程的地址空间以完全随机的方式投影到物理RAM上(具有一些固定粒度,通常为4K)。 彼此相邻的地址空间页不必被投影到RAM的相邻物理页面中。 RAM的物理页面不必与进程的地址空间页面保持相同的相对顺序。 这一切意味着在RAM中不存在这样的分割,并且不可能存在。
为了优化内存访问,操作系统可能(通常会)试图将进程地址空间的顺序页面映射到RAM中的顺序页面,但这只是一种优化。 一般情况下,映射是不可预测的。 除此之外,RAM被系统中的所有进程共享,属于不同进程的RAM页在RAM中被任意交错,这消除了在RAM中具有这种“段”的可能性。 RAM中没有特定的进程顺序或分段。 RAM只是虚拟内存机制的缓存。
同样,每个进程都有自己的虚拟地址空间。 这是这些细分市场可以存在的地方。 该进程不能直接访问RAM。 该过程甚至不需要知道RAM是否存在。
这些段在很大程度上方便了程序加载器和操作系统(尽管它们也为粗粒度的保护提供了基础;执行权限可以限制在文字上,禁止从数据中删除)。
物理内存地址空间可能被分割,但不是为了这些应用程序段。 例如,在NUMA系统中,硬件可能会使用特定的位来指示哪个节点拥有给定的物理地址。
对于使用地址转换的系统,操作系统可以在某种程度上随意地将这些段放在物理内存中。 (通过分段翻译,外部分段可能成为一个问题;连续的物理内存地址范围可能无法使用,需要昂贵的内存段移动。使用分页翻译,外部分段是不可能的。分段翻译的优点是需要较少翻译信息:每个段只需要一个基础并与其他元数据绑定,而内存段通常会有两个以上的页面,每个页面都有一个基本地址和元数据。)
如果没有地址转换,分段的放置不一定是随意的。 幸运的是,大多数程序并不关心分段放置的具体地址。 (单地址空间操作系统
(请注意,对于可共享部分来说,它们可以方便地位于固定位置,对于代码,这可以用来避免通过全局偏移表进行间接寻址,而不需要在程序加载器/动态链接器中进行二进制重写,这也可以减少地址转换开销。 )
应用程序级编程通常从这种分割中抽象出来,以至于它的存在不明显。 然而,对于物理资源使用的强化优化,包括执行时间,纯粹的抽象自然是不友好的。
另外,编程系统可以选择使用更复杂的数据放置(无需应用程序员需要知道实现细节)。 例如,使用协程可能会鼓励使用不需要连续性的仙人掌/意大利面条栈。 同样,垃圾收集运行时可能会提供额外的地址空间划分,不仅适用于托儿所,而且还用于从非叶对象(减少标记/扫描的开销)中分离没有可收集内存的引用的叶对象。 提供两个堆栈段(一个用于未获取地址的数据(或至少是固定大小的数据)和一个用于其他数据)也并不是特别罕见。
1对于类Unix操作系统,在扁平虚拟地址空间中,这些段的传统布局(堆栈向下增长)将文本放置在最低地址处,即立即在此之上的rodata,立即在其之上初始化数据,立即执行零初始化数据(bss)在这之上,堆从bss顶部向上生长,堆栈从虚拟地址空间的应用程序部分的顶部向下生长。
让堆栈和堆栈相互增长可以实现每个堆栈的任意增长(对于使用该地址空间的单个线程!)。 此放置还允许程序加载器将程序文件简单地复制到从最低地址开始的内存中,通过权限对内存进行分组,并且有时可以允许单个全局指针来解决所有全局/静态数据范围(数据,数据和BSS)。
进程的内存映射看起来被分割成段(堆栈,堆,bss,数据和文本)
这是Unix使用的基本映射; 其他操作系统使用不同的方案。 但是,一般来说,它们将进程内存空间分割为独立的段来执行代码,堆栈,数据和堆数据。
我想知道这些段是否仅仅是易于理解的进程的抽象,而物理RAM只是一个线性的地址数组,或者物理RAM也被分段到这些段中?
依靠。 是的,这些细分受众群是由操作系统创建和管理的,有利于该流程。 但物理内存可以排列为线性地址或分段分段,或非连续的RAM块。 操作系统需要管理整个系统内存空间,以便每个进程都可以访问自己的部分内存。
虚拟内存增加了另一层抽象层,因此看起来像线性内存位置的东西实际上被映射到单独的RAM页面,这可能在物理地址空间的任何地方。
另外,如果RAM不是碎片化的,并且只是一个线性阵列,那么操作系统如何提供这些过程的抽象?
操作系统通过使用虚拟内存映射硬件来管理所有这些。 每个进程都会看到其代码,数据,堆栈和堆段的连续内存区域。 但实际上,操作系统将这些段中的每一个页面映射到RAM的物理页面。 因此,两个相同的正在运行的进程将看到由连续的内存段组成的相同的虚拟地址空间,但是包含这些段的内存页面将被映射到完全不同的物理RAM页面。
但请记住,物理RAM实际上可能不是一块连续的内存块,但实际上可能会跨多个不相邻的块或内存组分割。 操作系统要以对进程透明的方式管理所有这些。
而且,如果内存映射到一个进程会像线性阵列一样出现并且不会被分成多个段,那么编程将如何改变,然后MMU会将这些虚拟地址转换为物理地址。
MMU总是以这种方式运行,将虚拟内存地址转换为物理内存地址。 OS为每个进程设置和管理每个段的每个页面的映射。 例如,每当进程超出其堆栈分配时,操作系统会捕获段故障并将另一页添加到进程的堆栈段,将虚拟页映射到从可用内存中选择的物理页。
虚拟内存还允许操作系统临时将进程页交换到磁盘,以便所有运行进程占用的虚拟内存总量可轻松超过系统的实际物理内存RAM空间。 只有当前活动的执行进程实际上可以访问真实的物理RAM页面。
链接地址: http://www.djcxy.com/p/82379.html