Linux存储管理方式

Linux存储管理方式,第1张

这种方式中,将用户程序的地址空间,注意,是 用户程序的地址空间 分为若干个固定大小的区域,成为“页”或“页面”。我们可以知道,这也页其实是不存在的,只是一种划分内存空间的方法。也就是说,这种方式将用户的程序 “肢解” 了,分成很多个小的部分,每个部分称为一个“页”。

将逻辑地址的前n位作为页号,后面32-n位作为页内偏移量。

由于进程的最后一页经常装不满一个块,从而形成了不可利用的碎片,称之为 “页内碎片”

作用:实现页号到物理号的地址映射。

页表是记录逻辑空间(虚拟内存)中每一页在内存中对应的物理块号。但并非每一页逻辑空间都会实际对应着一个物理块,只有实际驻留在物理内存空间中的页才会对应着物理块。

系统会为每一个进程建立一张页表,页表是需要一直驻留在物理内存中的(多级页表除外),另外页表的起址和长度存放在 PCB(Process Control Block)进程控制结构体中。

可以在页表的表项中设置相关的权限控制字段,例如设置存取控制字段,用于保护该存储块的读写;若存取控制字段为2位,则可以设置读/写、只读和只执行等存取方式。

物理块是实实在在存在于内存中的:

由于执行频率高,要求效率比较高,需要使用硬件实现。

在系统中设置一个 页表寄存器(PTR) ,其中存放页表在内存的起始地址和页表的长度。平时进程未执行的时候,页表的起始地址和页表长度放在本进程的PCB中。当调度程序调度到某个进程的时候,才将这两个数据装入 页表寄存器

变换过程:

快表的变换机构

为了提高地址变换速度,可在地址变换机构中增设一个具有并行查询能力的特殊高速缓冲寄存器,又称为"联想寄存器"或者“快表”。俗称TLB。

快表与页表的功能类似,其实就是将一部分页表存到 CPU 内部的高速缓冲存储器 Cache。CPU 寻址时先到快表查询相应的页表项形成物理地址,如果查询不到,则到内存中查询,并将对应页表项调入到快表中。但,如果快表的存储空间已满,则需要通过算法找到一个暂时不再需要的页表项,将它换出内存。

由于成本的关系,快表不可能做得很大,通常只存放 16~512 个页表项,这对中、小型作业来说,已有可能把全部页表项放在快表中;但对于大型作业而言,则只能将其一部分页表项放入其中。由于对程序和数据的访问往往带有局限性,因此,据统计,从快表中能找到所需页表项的概率可达 90% 以上。这样,由于增加了地址变换机构而造成的速度损失可减少到 10% 以下,达到了可接受的程度。

我们可以采用这样两个方法来解决这一问题:

① 对于页表所需的内存空间,可采用离散分配方式,以解决难以找到一块连续的大内存空间的问题;

只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。

二级页表的页表项:

过程:

在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对于内页表则只需调入一页或几页。为了表征某页的页表是否已经调入内存,还应在外层页表项中增设一个状态位 S,其值若为 0,表示该页表分页不在内存中,否则说明其分页已调入内存。进程运行时,地址变换机构根据逻辑地址中的 P1去查找外层页表;若所找到的页表项中的状态位为 0,则产生一个中断信号,请求 OS 将该页表分页调入内存。

多级页表和二级页表类似。多级页表和二级页表是为了节省物理内存空间。使得页表可以在内存中离散存储。(单级页表为了随机访问必须连续存储,如果虚拟内存空间很大,就需要很多页表项,就需要很大的连续内存空间,但是多级页表不需要。)

为什么引入分段存储管理?

引入效果:

它将用户程序的地址空间分为若干个大小不同的的段,每个段可以定义一组完整的信息。

段号表示段名,每个段都从0开始编址,并且采用一段连续的地址空间。

在该地址结构中,允许一个作业最长有64K个段,每个段的最大长度为64KB。

在分段式存储管理系统中,为每一个分段分配一个连续的分区。进程的各个段,可以离散地装入内存中不同的分区中。

作用:实现从逻辑地址到物理内存区的映射。

为了保证程序能够正常运行,就必须能够从物理内存中找出每个逻辑段所对应的位置。为此在系统中会为每一个进程建立一张 段表 。每个段在表中有一个表项,其中记录了该段在内存中的起始地址和段的长度。一般将段表保存在内存中。

在配置了段表之后,执行的过程可以通过查找段表,找到每一个段所对应的内存区。

为了实现进程从逻辑地址到物理地址的变换功能,在系统设置了段表寄存器,用于存放段表的起始地址和段表长度TL。

在进行地址变换时,系统将逻辑地址中的段号与段表长度TL 进行比较。若 S >TL,表示段号太大,是访问越界,于是产生越界中断信号。若未越界,则根据段表的始址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存的起始地址。然后,再检查段内地址 d 是否超过该段的段长 SL。若超过,即 d>SL,同样发出越界中断信号。若未越界,则将该段的基址 d 与段内地址相加,即可得到要访问的内存。

分页和分段系统相似之处:两者都采用离散分配方式,且都是通过地址映射机构实现地址变换。

但在概念上两者完全不同,主要表现在下述三个方面:

分页系统以页面作为内存分配的基本单位,能有效地提高内存利用率,而分段系统以段作为内存分配的基本单位,它能够更好地满足用户多方面的需要。

段页式地址结构由段号、段内页号及页内地址三部分所组成

段页式系统的基本原理是分段和分页原理的结合,即先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名。如下图展示了一个作业地址空间的结构。该作业有三个段:主程序段、子程序段和数据段;页面大小为 4 KB:

在段页式系统中,为了实现从逻辑地址到物理地址的变换,系统中需要同时配置段表和页表。段表的内容与分段系统略有不同,它不再是内存始址和段长,而是页表始址和页表长度。下图展示出了利用段表和页表进行从用户地址空间到物理(内存)空间的映射。

在段页式系统中,为了便于实现地址变换,须配置一个段表寄存器,其中存放段表始址和段长 TL。进行地址变换时,首先利用段号 S,将它与段长 TL 进行比较。若 S <TL,表示未越界,于是利用段表始址和段号来求出该段所对应的段表项在段表中的位置,从中得到该段的页表始址,并利用逻辑地址中的段内页号 P 来获得对应页的页表项位置,从中读出该贝所在的物理块号 b,再利用块号 b 和页内地址来构成物理地址。

在段页式系统中,为了获得一条指令或数据,须三次访问内存。第一次访问是访问内存中的段表,从中取得页表始址;第二次访问是访问内存中的页表,从中取出该页所在的物理块号,并将该块号与页内地址一起形成指令或数据的物理地址;第三次访问才是真正从第二次访问所得的地址中取出指令或数据。

显然,这使访问内存的次数增加了近两倍。为了提高执行速度,在地址变换机构中增设一个高速缓冲寄存器。每次访问它时,都须同时利用段号和页号去检索高速缓存,若找到匹配的表项,便可从中得到相应页的物理块号,用来与页内地址一起形成物理地址:若未找到匹配表项,则仍需第三次访问内存。

参考链接:

维基百科——虚拟内存定义

All about Linux swap space

Linux将物理RAM (Random Access Memory) 划分为称为页面的内存块。交换是将一页内存复制到硬盘上的预配置空间(称为交换空间)以释放改内存页面上的过程。物理内存和交换空间的组合就是可用的虚拟内存量。

虚拟内存的那点事儿

进程是与其他进程共享CPU和内存资源的。为了有效的管理内存并减少出错,现代 *** 作系统提供了一种对主存的抽象概念,即:虚拟内存( Virtual Memory )。 虚拟内存为每个进程提供一个一致的,私有的地址空间,每个进程拥有一片连续完整的内存空间。

正如 维基百科 所说,虚拟内存不只是“使用硬盘空间来扩展内存”的技术。 虚拟内存的重要意义是它定义了一个连续的虚拟地址空间, 使得程序编写难度降低。并且, 把内存扩展到硬盘空间只是使用虚拟内存的必然结果,虚拟内存空间会存在硬盘中,并且会被全部放入内存中缓冲(按需),有的 *** 作系统还会在内存不够的情况下,将一进程的内存全部放入硬盘空间中,并在切换到进程时再从硬盘读取 (这也是Windows会经常假死的原因...)。

虚拟内存主要提供了如下三个重要的能力:

内存通常被组织为一个由M个连续的字节大小的单元组成的数组。每个字节都有一个唯一的物理地址 (Physical Address PA) ,作为到数组的索引。

CPU访问内存最简单直接的方法就是使用物理地址,这种寻址方式称为 物理寻址

现代计算机使用的是一种被称为虚拟寻址 (Virtual Addressing) 的寻址方式。 使用虚拟寻址,CPU需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。

虚拟寻址需要硬件与 *** 作系统之间相互合作。 CPU中含有一个被称为内存管理单元 (Memory Management Unit,MMU) 的硬件,它的功能是将虚拟地址转换称为物理地址,MMU需要借助存放在内存中的 页表 来动态翻译虚拟地址,该页表由 *** 作系统管理。

分页表是一种数据结构,它用于计算机 *** 作系统中虚拟内存系统,其存储了虚拟地址到物理地址之间的映射。虚拟地址在访问进程中是唯一的,而物理地址在硬件(比如内存)中是唯一的。

在 *** 作系统中使用 虚拟内存 ,每个进程会认为使用一块大的连续的内存,事实上,每个进程的内存散布在 物理内存 的不同区域。或者可能被调出到备份存储中(一般是硬盘)。当一个进程请求自己的内存, *** 作系统负责把程序生成的虚拟地址,映射到实际存储的物理内存上。 *** 作系统在 分页表 中存储虚拟地址到物理地址的映射。每个映射被称为 分页表项(page table entry ,PTE)

在一个简单的地址空间方案中,由虚拟地址寻址的页与物理内存中的帧之间的关系。物理内存可以包含属于许多进程的页。如果不经常使用,或者物理内存已满,可以将页面分页到磁盘。在上图中,并非所有页面都在物理内存中。

虚拟地址到物理地址的转换(即虚拟内存的管理)、内存保护、CPU高速缓存的控制。

现代的内存管理单元是以 的方式,分割虚拟地址空间(处理器使用的地址范围)的;页的大小是2的n次方,通常为几KB(字节)。地址尾部的n位(页大小的2的次方数)作为页内的偏移量保持不变。其余的地址位(address)为(虚拟)页号。

内存管理单元通常借助一种叫做转译旁观缓冲器(Translation Lookaside Buffer,TLB)和相联高速缓存来将虚拟页号转换为物理页号。当后备缓冲器中没有转换记录时,则使用一种较慢的机制,其中包括专用硬件的数据结构或软件辅助手段。这个数据结构称为 分页表 ,页表中的数据叫做 分页表项 (page table entry PTE)。物理页号结合页偏移量便提供了完整的物理地址。

页表 或 转换后备缓冲器数据项应该包括的信息有:

有时候,TLB和PTE会 禁止对虚拟页访问 ,这可能是因为没有RAM与虚拟页相关联。如果是这种情况,MMU将向CPU发出页错误的信号, *** 作系统将进行处理,也许会寻找RAM的空白帧,同时建立一个新的PTE将之映射到所请求的虚拟地址。如果没有空闲的RAM,可能必须关闭一个已经存在的页面,使用一些替换算法,将之保存到磁盘中(这被称为页面调度)。

当需要将虚拟地址转换为物理地址时,首先搜索TLB,如果找到匹配(TLB)命中,则返回物理地址并继续存储器访问。然而,如果没有匹配(称为TLB未命中),则MMU或 *** 作系统TLB未命中处理器通常会查找 页表 中的地址映射以查看是否存在映射(页面遍历),如果存在,则将其写回TLB(这必须完成,因为硬件通过虚拟存储器系统中的TLB访问存储器),并且重启错误指令(这也可以并行发生)。此后续转换找到TLB命中,并且内存访问将继续。

虚拟地址到物理地址的转换过程,如果虚拟内存不存在与TLB,转换会被重置并通过分页表和硬件寻找。

通常情况下,用于处理此中断的程序是 *** 作系统的一部分。如果 *** 作系统判断此次访问有效,那么 *** 作系统会尝试将相关的分页从硬盘上的虚拟内存文件调入内存。 而如果访问是不被允许的,那么 *** 作系统通常会结束相关的进程。

虽然叫做“页缺失”错误,但实际上这并不一定是一种错误。而且这一机制是利用虚拟内存来增加程序可用内存空间。

发生这种情况的可能性:

当原程序再次需要该页内的数据时,如果这一页确实没有被分配出去,那么系统只需要重新为该页在MMU内注册映射即可。

*** 作系统需要:

硬性页缺失导致的性能损失是很大的。

另外,有些 *** 作系统会将程序的一部分延迟到需要使用的时候再加载入内存执行,以此提升性能。这一特性也是通过捕获硬性页缺失达到的。

当硬性页缺失过于频繁发生时,称发生 系统颠簸。

具体动作与所使用的 *** 作系统有关,比如Windows会使用异常机制向程序报告,而类Unix系统则使用信号机制。

尽管在整个运行过程中,程序引用不同的页面总数(也就是虚拟内存大小)可能超出了物理存储器(DRAM)总大小,但是程序常常在较小的活动页面上活动,这个集合叫做工作集或者常驻集。在工作集被缓存后,对它的反复调用会使程序命中提高,从而提高性能。

大部分的程序都可以在存储器获取数据和读取中达到稳定的状态,当程序达到稳定状态时,存储器的使用量通常都不会太大。虚拟内存虽然可以有效率控制存储器的使用, 但是大量的页缺失还是造成了系统迟缓的主要因素。 当工作集的大小超过物理存储器大小,程序将会发生一种不幸的情况,这种情况称为 “颠簸” ,页面将不停的写入、释放、读取,由于大量的丢失(而非命中)而损失极大性能。用户可以增加随机存取存储器的大小或是减少同时在系统里运行程序的数量来降低系统颠簸的记录。

推荐阅读:

*** 作系统--分页(一)

*** 作系统实现(二):分页和物理内存管理


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8781581.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-21
下一篇2023-04-21

发表评论

登录后才能评论

评论列表(0条)

    保存