操作系统面经 - 内存管理

目录

 

1 硬盘基础知识

1.1 磁盘容量计算

1.2 磁盘读取响应时间

1.3 磁盘块/簇 页page 扇区 的关系

2 内存管理

2.1 为什么要有内存

2.2 内存,磁盘,cpu,缓存,虚拟内存 关系

2.3 虚拟内存

2.4 计算机运行程序的过程

3 指令

3.1 主机字节序与网络字节序

4 用户态、内核态


1 硬盘基础知识

盘片 片面 和 磁头:硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。

扇区 和 磁道: 下图显示的是一个盘面,盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将磁道划分为若干个弧段,每个磁道上一个弧段被称之为一个扇区(图践绿色部分)。扇区是磁盘的最小组成单元,通常是512字节。(由于不断提高磁盘的大小,部分厂商设定每个扇区的大小是4096字节)

磁头 和 柱面:硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外边的 “0” 开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。

 

1.1 磁盘容量计算

存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数

上图磁盘是一个3个圆盘6个磁头,7个柱面(每个盘片7个磁道) 的磁盘,图3中每条磁道有12个扇区,所以此磁盘的容量为:

存储容量 6 * 7 * 12 * 512 = 258048

每个磁道的扇区数一样是说的老的硬盘,外圈的密度小,内圈的密度大,每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。

1.2 磁盘读取响应时间

  1. 寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms,一般都在10ms左右。

  2. 旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转速。普通硬盘一般都是7200rpm,慢的5400rpm。

  3. 数据传输时间:完成传输所请求的数据所需要的时间。

寻道时间和旋转延迟 是最受关注的两个事件

读写一次磁盘信息所需的时间可分解为:寻道时间、延迟时间、传输时间。为提高磁盘传输效率,软件应着重考虑减少寻道时间和延迟时间。

1.3 磁盘块/簇 页page 扇区 的关系

磁盘块/簇是虚拟出来的。 块/簇是操作系统中最小的逻辑存储单位。

(通俗的来讲,在Windows下如NTFS等文件系统中叫做簇;在Linux下如Ext4等文件系统中叫做块(block)。每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。)

页page也是虚拟出来的。操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,与内存进行通信的时候要一种虚拟的基本单位,虚拟一个"页"的概念来作为最小单位。==》与硬盘打交道,就是以块为最小单位。与内存打交道,就是以也为最小单位。

为什么存在磁盘块 / 页?

    1) 读取方便:由于一个扇区的能存储的字节比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。

    2) 分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。

扇区、块/簇、page的关系

  1. 扇区: 硬盘的最小读写单元

  2. 块/簇: 是操作系统针对硬盘读写的最小单元

  3. page: 是内存与操作系统之间操作的最小单元。

扇区 <= 块/簇 <= page

2 内存管理

2.1 为什么要有内存

(阅读了解就可以)

在早些的操作系统中,并没有引入内存抽象的概念,直接把物理地址暴露给进程。程序直接访问和操作的都是物理内存。比如当执行如下指令时:mov reg1,1000 这条指令会毫无想象力的将物理地址1000中的内容赋值给寄存器。这种内存操作方式使得操作系统中存在多进程变得完全不可能,你必须执行完一条指令后才能接着执行下一条。如果是多进程的话,由于直接操作物理内存地址,当一个进程给内存地址1000赋值后,另一个进程也同样给内存地址赋值,那么第二个进程对内存的赋值会覆盖第一个进程所赋的值,这回造成两条进程同时崩溃。

存储地址空间:基址寄存器与界限寄存器可以简单的动态重定位,每个内存地址送到内存之前,都会自动加上基址寄存器的内容,之后再去物理地址哪里找到内存空间。这样用户每次只访问有需要的内容。交换技术把一个进程完全调入内存,使该进程运行一段时间,然后把它存回磁盘。空闲进程主要存在磁盘上,所以当他们不运行时就不会占用内存。

无内存抽象存在的问题 / 为什么要有内存地址空间:

  1. 用户程序可以访问任意内存,可以寻址内存的每个字节,就有很大的可能破坏操作系统,造成系统崩溃。

  2. 同时运行多个程序特别困难。地址空间创造了一个新的内存抽象,地址空间是一个进程可用于寻址内存的一套地址的集合。每个进程都有一个自己的地址空间,并且这个地址空间独立于其它进程的地址空间。使用基址寄存器和界限器可以实现。

2.2 内存,磁盘,cpu,缓存,虚拟内存 关系

磁盘是外存,内存条上放着内存。缓存是内存的组成部分。虚拟内存是有了内存后,不直接暴露物理地址,因此就要有一个新的内存抽象,就是虚拟内存。

前面都是在存储,CPU没有存储能力,只有一些寄存器能临时存储,CPU的计算能力很强。

2.2.1 CPU

CPU没有存储能力,只有为数不多的寄存器能临时存储一点东西。但是CPU的运算力很强。寄存器是中央处理器内的组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。

2.2.2 内存 RAM

内存即RAM,随机存取存储器,是与CPU直接交换数据的内部存储器。它用来加载各种各样的数据和程序以供CPU直接运行与运用。它的物理实质就是一组或多组具备数据输入输出和数据存储功能的集成电路,是可以随时读写的,并且速度也很快,仅仅比CPU慢100倍。内存就是用来临时存储数据,用来给CPU提供CPU要处理的东西。但是内存不会长期保存数据,只是临时存储,程序和数据处理完后就释放空间。 内存包含的范围非常广,一般分为只读存储器(ROM)、随机存储器(RAM)和高速缓存存储器(cache)。

为什么CPU从内存读数据:

CPU要从内存中取数据而不直接从硬盘取数据。因为CPU的运算速度太快,而硬盘是通过机械的方式读取数据因此速度很慢。如果直接从硬盘读取数据CPU的工作效率就很低。为了提高CPU的工作效率,就设计出了存储器的层次结构,在CPU处理程序的过程中,可以将下一步要执行的指令预加载并缓存。

2.2.3 缓存 Cache

Cache :即高速缓冲存储器,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache),L1 Cache集成在CPU内部,L2 Cache早期一般是焊在主板上,现在也都集成在CPU内部,常见的容量有256KB或512KB L2 Cache。

为什么要有Cache:

Cache缓存则是为了弥补CPU与内存之间运算速度的差异而设置的的部件。而内存中被CPU访问最频繁的数据和指令就被复制入CPU中的缓存。也就是cache。总结:大致来说数据是通过内存-Cache-寄存器。

2.2.4 外存(辅存)

外存通常是磁性介质或光盘,像硬盘,软盘,磁带,CD等,能长期保存信息,并且不依赖于电来保存信息,但是由机械部件带动,速度与CPU相比就显得慢的多。

硬盘即HDD(Hard Disk Drive)。硬盘是计算机上使用坚硬的旋转盘片为基础的非挥发性存储设备,它在平整的磁性表面存储和检索数字数据,信息通过离磁性表面很近的磁头,由电磁流来改变极性方式被电磁流写到磁盘上,信息可以通过相反的方式读取,例如读头经过纪录数据的上方时磁场导致线圈中电气信号的改变。硬盘的读写是采用随机存取的方式,因此可以以任意顺序读取硬盘中的数据。硬盘就是存东西的,硬盘会长期存储数据,只要是不人为删除,不出现硬件故障,东西就不会丢。

2.3 虚拟内存

为什么要有虚拟内存?

有了内存,就不需要直接把数据的物理地址暴露给计算单元,因为中间有内存。这样就创造了一个新的内存抽象,每个进程都有一个自己的地址空间,可以对自己的数据进行删改,之后再通过指令对物理上的数据统一更改。这些的前提就是内存上可以存放当前正在运行的几个进程的全部数据/指令。但是很多情况下,现有内存无法满足仅仅一个大进程的内存要求。因此引入虚拟内存解决。

虚拟内存的实现?

每个进程有独立的逻辑地址空间,这个逻辑空间是虚拟的。他通过映射去找他的真实空间,因此有的虚拟内存映射到物理内存有的映射到硬盘。虚拟内存的基本单位是页。每个页内部是一段连续的地址。因此虚拟内存实际上可以比物理内存大。当访问虚拟内存时,会通过MMU(内存管理单元)去匹配对应的物理地址,而如果虚拟内存的页并不存在于物理内存中,会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种置换算法将磁盘中的页换出。

2.3.1 页表

虚拟内存和物理内存的匹配是通过页表实现,页表存在MMU(内存管理单元)中,页表中每个项通常为32位,既4byte,除了存储虚拟地址和页框地址之外,还会存储一些标志位,比如是否缺页,是否修改过,写保护等。

因为页表中每个条目是4字节,现在的32位操作系统虚拟地址空间会是2的32次方,即使每页分为4K,也需要2的20次方 * 4字节 = 4M的空间。

为每个进程建立一个4M的页表并不明智。因此在页表的概念上进行推广,产生二级页表,二级页表每个对应4M的虚拟地址,而一级页表去索引这些二级页表,因此32位的系统需要1024个二级页表,虽然页表条目没有减少,但内存中可以仅仅存放需要使用的二级页表和一级页表,大大减少了内存的使用。

引入多级页表的原因是避免把全部页表一直存在内存中。

2.3.2 虚拟内存地址 <=>物理内存地址 映射

虚拟地址和物理地址匹配规则

虚拟页号可用做页表的索引,以找到该虚拟页面对应页表项。由页表项可以找到页框号。然后把页框号拼接到偏移量的高位端,以替换虚拟页号,形成送往内存的物理地址。

页表的目的是把虚拟页面映射为页框,从数学的角度来说,页表是一个函数,它的参数是,虚拟页号,结果是物理页框号。通过这个函数可以把虚拟地址中的虚拟页面域替换为页框域,从而形成物理地址。

2.3.3 页面置换算法

在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。

分为:全局置换:在整个内存空间置换  和  局部置换:在本进程中进行置换

算法:

全局置换: 工作集算法  /  缺页率置换算法

局部置换:最佳置换算法(OPT)/  先进先出置换算法(FIFO)  /  最近最久未使用(LRU)算法  /  时钟(Clock)置换算法

最佳置换算法(OPT):未来保证获得最低的缺页率,被淘汰页面是以后永不使用或最长时间内不再访问的页面。往后看

先进先出置换算法(FIFO):  选择驻留主存时间最长的页面进行淘汰,理由:最早调入主存的页面不再被使用的可能性最大。 FIFO算法还会产生当所分配的物理块数增大而页故障数不减反增的异常现象,称为Belady异常。LRU和OPT算法永远不会出现Belady异常。往前看

最近最久未使用(LRU)算法:利用局部性原理,当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。往前看

LRU算法的性能接近于OPT,但实现比较困难,且开销大;FIFO算法实现简单,但性能差。

时钟(Clock)置换算法 / 最近未用(Not Recently Used, NRU)算法:简单的CLOCK算法是给每一帧关联一个附加位,称为使用位。当某一页首次装入主存时,该帧的使用位设置为1;当该页随后再被访问到时,它的使用位也被置为1。对于页替换算法,用于替换的候选帧集合看做一个循环缓冲区,并且有一个指针与之相关联。当某一页被替换时,该指针被设置成指向缓冲区中的下一帧。当需要替换一页时,操作系统扫描缓冲区,以查找使用位被置为0的一帧。每当遇到一个使用位为1的帧时,操作系统就将该位重新置为0;如果在这个过程开始时,缓冲区中所有帧的使用位均为0,则选择遇到的第一个帧替换;如果所有帧的使用位均为1,则指针在缓冲区中完整地循环一周,把所有使用位都置为0,并且停留在最初的位置上,替换该帧中的页。由于该算法循环地检查各页面的情况,故称为CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法

2.3.4 分页系统中的设计问题

在任何分页式系统中为进程分配内存时,将涉及到3个问题:

1)最小物理块数的确定;2)物理块的分配策略;3)物理块的分配算法

1、最小物理块数的确定: 是指能保证进程正常运行所需的最小物理块数。当系统为进程分配的物理块数小于此值时,进程将无法运行。进程应获得的最少物理块数与计算机的硬件结构有关,取决于指令的格式、功能和寻址方式

2、物理块的分配策略 :在请求分页系统中,可采取两种内存分配策略,即固定可变分配策略。在进行置换时,也可采取两种策略,即全局置换局部置换

---- 全局是指置换页面时,换出的页面可能是内存中的任一进程的页面,局部只能是本(缺页)进程的页面。

---- 固定分配指为一个进程分配的物理块是固定的,可变分配指可根据缺页率调整所分配的物理块数。

   于是可组合出以下三种适用的策略。

1)固定分配局部置换(Fixed Allocation,Local Replacement):这是指基于进程的类型(交互型或批处理型等),或根据程序员、程序管理员的建议,为每个进程分配一定数目的物理块,在整个运行期间都不再改变。采用该策略时,如果进程在运行中发现缺页,则只能从该进程在内存的n个页面中选出一个页换出,然后再调入一页,以保证分配给该进程的内存空间不变(固定分配)。

---- 实现这种策略的困难在于:应为每个进程分配多少个物理块难以确定。若太少,会频繁地出现缺页中断,降低了系统的吞吐量;若太多,又必然使内存中驻留的进程数目减少,进而可能造成CPU空闲或其他资源空闲的情况,而且在实现进程对换时,会花费更多的时间。

2)可变分配全局置换(Variable Allocation,Global Replacement):在采用这种策略时,先为系统中的每个进程分配一定数目的物理块,而OS自身也保持一个空闲物理块队列。当某进程发现缺页时,由系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的(缺)页装入其中。这样,凡产生缺页(中断)的进程,都将获得新的物理块。仅当空闲物理块队列中的物理块用完时,OS才能从内存中选择一页调出,该页可能是系统中任一进程的页,这样,自然又会使那个进程的物理块减少,进而使其缺页率增加。

3)可变分配局部置换(Variable Allocation,Local Replacement):为每个进程分配一定数目的物理块,但当某进程发现缺页时,只允许从该进程在内存的页面中选出一页换出,这样就不会影响其它进程的运行。如果进程在运行中频繁地发生缺页中断,则系统需再为该进程分配若干个附加的物理块,直至该进程的缺页率减少到适当程度为止;反之,若一个进程在运行过程中的缺页率特别低,则此时可适当减少分配给该进程的物理块数,但不应引起其缺页率的明显增加。

3、物理块分配算 :在采用固定分配策略时,有3种方法将系统中可供分配的所有物理块分配给各个进程。平均分配算法:将系统中所有可供分配的物理块平均分配给各个进程。(它未考虑到各进程本身的大小。)  /  按比例分配算法  /  考虑优先权的分配算法:把内存中可供分配的所有物理块分成两部分,一部分按比例地分配给各进程,另一部分则根据各进程的优先权,适当地增加其相应份额后,分配给各进程。在有的系统中,如重要的实时控制系统,则可能是完全按优先权来为各进程分配其物理块的。

 4、调页策略 : 主要考虑3个内容:预调页策略 / 请求调页策略 / 确定从何处调入页面 。 

请求分页系统中的外存分为两部分:文件区对换区(用于存放文件的文件区和用于存放对换页面的对换区)。

通常,对换区采用连续分配方式,文件区是采用非连续分配方式。故对换区的磁盘I/O速度比文件区的高。何处调入分3种情况:

-- 1)系统拥有足够的对换区空间,可全部从对换区调入所需页面。在进程运行前,需将与该进程有关的文件从文件区拷贝到对换区。

-- 2)系统缺少足够的对换区空间,不会被修改的文件都直接从文件区调入,当换出这些页面时,由于它们未被修改而不必将它们换出,以后再调入时,仍从文件区直接调入。对于那些可能被修改的部分,在将它们换出时,需调到对换区,以后需要从对换区调入。

-- 3)Unix方式。凡是未运行过的页面,都应从文件区调入。曾经运行过但又被换出的页面,放在对换区,调入时从对换区调入。Unix系统运行页面共享,因此某进程所请求的页面有可能已被其它进程调入内存,此时无需再从对换区调入。

5、负载控制:即使使用了最优的页面置换算法,最理想的全局分配。当进程组合的工作集超出内存容量时,就可能发生颠簸。这时只能根据进程的特性(IO 密集 or CPU 密集)将进程交换到磁盘上。

6、页面大小 的确定不存在全局最优的结果,小页面减少页面内内存浪费,但是小页面,意味着更大的页表,更多的计算转换时间。现在一般的页面大小是 4KB 或 8KB。地址空间太小,所以分离指令空间,数据空间

虚拟地址到到物理地址的映射必须非常快;如果虚拟地址空间很大,页表也会很大。

2.4 计算机运行程序的过程

当计算机运行程序时,首先,会通过IO总线将程序指令和数据加载到内存中,其次,CPU通过总线从内存中获取指令和数据并将其存放在CPU内部的寄存器中,并对指令译码进行分解,最后,在CPU内部根据指令在运算器中对数据进行操作。

3 指令

指令是计算机CPU真正运行的数据,也就是计算机执行的机器代码,用字节序列编码的操作。指令是由指令集架构定义的单个的CPU操作。在更广泛的意义上,指令可以是任何可执行程序元素的表属,例如字节码。指令包括一个操作码——它指定了要进行什么样的操作。CPU通过寄存器中的指令来进行数据的操作。另外,指令一般有四种:加载、存储、操作和跳转。

3.1 主机字节序与网络字节序

主机字节序又叫 CPU 字节序,其不是由操作系统决定的,而是由 CPU 指令集架构决定的。主机字节序分为两种:

  • 大端字节序(Big Endian):高序字节存储在低位地址,低序字节存储在高位地址

  • 小端字节序(Little Endian):高序字节存储在高位地址,低序字节存储在低位地址

4 用户态、内核态

为什么有内核态和用户态:

由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态和内核态。

所有用户程序都是运行自己的代码时处于用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要通过操作系统请求以程序的名义来执行这些操作.这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令。这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction),当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。

他们的工作流程如下:

  1. 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.

  2. 用户态程序执行陷阱指令

  3. CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问

  4. 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务

  5. 系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果

此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。

此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。 

内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然的联系, intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。Linux使用了Ring3级别运行用户态,Ring0作为 内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部 分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运 行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必 须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能 随意操作内核地址空间,具有一定的安全保护作用。

至于说保护模式,是说通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值