操作系统之哲学思想之内存原理

一、基本内存

1.1、内存管理:是对内存架构进行管理,使程序在内存架构的任何一个层次上的存放对于用户来说都是一样的。

       内存管理实现这种媒介透明的手段就是虚拟内存

1.2、内存管理要达到什么目的?

  地址保护(互不干扰):多道程序同时存放在内存中,操作系统要保证它们之间互不干扰(一个进程不能随便访问另一个进程的地址空间)。

  地址独立:程序发出的地址应与物理主存地址无

1.3、虚拟内存

  中心思想:将物理主存扩大到便宜、大容量的磁盘上,即将磁盘空间看作是主存空间的一部分。

  虚拟内存要提供的就是一个空间像磁盘那样大、速度像缓存那样高的主存储系统,而对程序地址所在的位置(缓存、主存、磁盘)的判断则是内存管理系统的一个中心功能。

1.4、内存管理方法 

  •   单道编程的内存管理
    •  固定加载地址的内存管理
  •   多道编程的内存管理-------实现机制:基址与极限
    •  固定分区的内存管理
    •    非固定分区的内存管理
    •    交换内存管理

  静态地址翻译:程序运行前即将物理地址计算好的方式

  动态地址翻译:程序运行时进行地址翻译

      • 一个虚拟地址仅在被访问的时候才需要放在内存里,其他时候并不需要占用内存。

 

 基址: 程序所在区域的起始地址成为基址

 工作原理:将程序发出的虚拟地址加上基址而获得物理地址。如果地址超过指定的极限,则视为地址出界而禁止访问,否则访问正常进行

    •  由于每个程序占用连续的一片内存空间,因此只要其访问的地址不超出该片连续空间,则为合法访问
    •  只需要设置两个端值:基址和极限,既可达到地址翻译和地址保护的目的;这两个端值分别由基址寄存器和极限寄存器存放

 一个程序的空间增长通常有两个来源:数据和栈

 

1.5、交换

  交换:将一个进程从内存倒出到磁盘上,再将其从磁盘上加载到内存中来的过程。

  目的:

    •  是为程序找到一片更大的空间,从而防止一个程序因空间不够而崩溃;(主要目的)
    •  实现进程切换,即将一个程序暂停一会,让另一个程序运行。(很少这么做)

二、页式内存管理

  空间碎片化的根源是每个程序的大小不一样,这样在空间分配时不存在一致性。

·  

  在分页系统下,一个程序发出的虚拟地址由两部分组成:页面号和页内偏移值

  分页系统的核心是页面的翻译,即从虚拟页面到物理页面的映射。这个翻译过程由内存管理单元(MMU)完成

MMU对虚拟地址的翻译只是对页面号的翻译,即将虚拟页面号翻译成物理页面号。而对偏移值,则不进行任何操作(虚拟页面里的偏移值和物理页面里的偏移值完全一样,无需翻译)

 

 

 

 非法虚拟页面:程序加载前所使用的一切地址均为虚拟地址,即程序存在于虚拟空间;一个程序没有使用的部分,这部分空间即为非法虚拟页面

e.g   对于32位寻址的系统,如果页面大小位4KB,则页面号占20位,页内偏移值占12位

   2^12=4k=4x1024 即页内偏移值12位

2.2、页表

  MMU是通过页表知道该页面是否有效、是否被保护、是否在物理内存。

  MMU是如何将虚拟地址转化为物理地址呢,它会去查询页表。MMU将虚拟地址转换为物理地址,不是按一个一个地址转换的,是以4k一页为单位转换的。

  页表:就是记录虚拟地址到物理地址映射规则的集合。

  对于每一个程序,MMU都为其保存一个页表,该表里面存放的是虚拟页面到物理页面的映射

MMU中有几个概念:
  PTE:页表项,即某条具体的转换规则,例如0x84050000这一页映射到0x8000物理页。
  TLB:翻译快表---MMU中的cache,用来缓存最近用过的PTE(TLB里面存放的是从虚拟页面到物理页面的映射,其记录的格式与内容和正常页表的记录格式与内容一样)

    • 缓存命中:解决翻译速度
    • TLB里面进行的同时比较,即将所有的TLB记录与目的虚拟地址同时比较,因此只需要一次查找就能确定一个虚拟页面号是否在TLB里面

页表的一个记录所包括的内容大致为如图所示:

 

  • 缓存禁止:用来指示该页面是否允许存放在缓存里
  • 访问位:记录该页面是否被访问过(被读过或者被写过)
  • 修改位:记录该页面自从加载到物理内存后是否被修改过。
  • 保护标识位:记录该页的受保护情况 (是否允许读、写、执行等)
  • 在内存否:记录该虚拟页面是否已经在物理内存里
  • 物理页面号:该虚拟页面对应的物理页面

注:访问位和修改位是MMU进行页面置换时依赖的信息

 

2.3、多级页表

  从上面可以看出,因为各个进程映射不同,每个进程必须有独立的页表。系统中如果有100个进程,则需要4*100=400M内存来存储页表,这是不行的。那么能不能不映射一些页呢? 不行,4G的空间哪些不用是未知的,所以必须提前都预留映射。

  假如一个进程需要使用100M的内存,那么1M个页表项中只有25k个是有用的,使用率百分之二,剩下的3.98M页表内存都浪费掉了。

  想要节省页表内存,就不能以4K为单位映射,要以4M为单位映射,页表只需要1K个,占用4K内存。每一个页表项指向4M的地址,需要第二级页表,第二级页表按照4k为单位映射的话,每个4M需要1k个页表项,占用4k内存。再算算上述一个进程需要100M内存,首先一级页表是4K,二级页表只需要25张*4k,全部页表只占用104k内存,相比4M节省了大部分内存,仅浪费了3.99K的内存。

  可以看到,使用多级页表,不仅节省每个进程的页表占用的内存,还能根据进程使用内存不同动态的调整页表占用内存的大小。

下面是一个虚拟地址0x3213 2160通过二级页表映射到物理地址的过程

事实上,在ARM架构中,这个访问过程是硬件实现的,但是页表的填充是软件维护的

 

2.4、缺页中断处理

   缺页中断程序是如何知道虚拟页面在磁盘的什么地方呢?

它不知道,但它知道产生缺页中断进程所对应的源程序文件名和产生缺页中断的虚拟地址。

这样,缺页中断服务程序首先根据虚拟地址计算出该地址在相应程序文件里面的位移量或偏移量(offset), 然后要求文件系统在这个偏移量的地方进行文件操作

  当一旦执该代码段时,由于页表项不存在,CPU会产生一次违例访存,跳进OS早早就调置好的缺页异常代码(do_page_fault),在do_page_fault函数内经过严密的安检之后,确认程序访存的合法性之后,就要将文件加载到内存中。

接着:do_page_fault根据vma里面描述的文件名,调用文系统接口将文件内存加载到物理内存中。等等……这个过程也涉及很复杂的加载过程,涉及磁盘访问,bio,以及pagecache,可以在知乎上找很多相关的描述。

最后:文件加载到物理内存(就是pagecache)后,可以修改页表项了,将页有的PFN填写成物理内存的页框号,访问属性等一系的页表位写之后,就算完了,返回用户态。继续执行。

 

 缺页中断的处理步骤:

  •   硬件陷入到内核
  •   保护通用寄存器
  •   操作系统判断所需的虚拟页面号
  •   操作系统检查地址的合法性
  •   操作系统选择一个物理页面用来存放将要调入的页面
  •   如果选择的物理页面包含有未写磁盘的内容,则首先进行写盘操作
  •   操作系统将新的虚拟页面调入内存
  •   更新页表
  •   发生缺页中断的程序进入就绪状态
  •   恢复寄存器
  •   程序继续

2.5、锁住页面

 
如何把页面锁在内存里面呢?

  只需要对该页面作出特殊标记,即在页表的相应记录项里增加一项标志。如果该标志被设置,缺页中断服务程序在选择被替换的页面时将跳过该页面。
 
 三、段式内存管理
 
 3.1、分段管理系统
  分段管理:将一个程序按照逻辑单元分成多个程序段,每一段使用自己单独的虚拟地址空间

 分段情况下,一个虚拟地址将由段号和段内偏差两部分构成

  分段管理的实现手段是:需要一组基址与极限对,而每一对基址极限用于其中一段的管理。

  分段管理的一个重要数据结构就是段表,由于段的数量少,通常为3~5段。

3.2、段页式内存管理

  段页式管理模式:在段里面分页,而每个段占住一个虚拟地址空间,即意味着一个程序将对应多个页表。

    由段号在段表里面获得所应使用的页表,然后在该页表里面查找物理页号

  Multics 段页式管理系统的段表记录包含的内容:

  

 

 是否分页:该标志用来表明该系统是否分页;0标识分页,1标识部分页。如果不分页,那就是纯逻辑分段

  

3.3、段号是否占用寻址字位

  在分段模式下,一条指令的虚拟地址包括段号和段内偏差。那么段号将不占用虚地址空间的字段

段号不占虚地址空间位数是如何实现的呢?

  使用单独的寄存器来存放段号,或者将段号隐含在指令操作码里,即每条指令都隐含了自己到底属于哪一个逻辑段

 

 

 

https://www.cnblogs.com/loveer/p/11703538.html

posted @ 2020-07-30 10:28  幻落之瞳  阅读(323)  评论(0编辑  收藏  举报