现代操作系统之内存管理(下)

分页设计中的设计问题

局部分配策略和全剧分配策略

全局算法在通常情况下工作得比局部算法号,当工作集的大小随进程允许时间发生变化时这种现象更加明显。

但是使用全局算法时,系统必须不停地取得应该给每个进程分配多少页框,一种方法是检测工作集的大小,工作集大小由老化位指出,但该方法不能防止颠簸

另一种图解是使用一个位进程分配页框但算法,为每个进程规定一个最小但页框数。

如果使用全局算法,根据进程但大小按比例为其分配页面也是可能的,当爱分配必须在程序运行时动态更新。管理内存动态分配的一种方法是PFF(缺页中断率)算法。他指出来何时增加或减少分配给一个进程的页面,但是五年前没有说明发生缺页时应该替换哪一个,它只是控制大小,

值得注意的是,一些页面置换算法既适用于局部置换算法,页适用于全局置换算法。


负载控制

一旦所有进程的组合工作集超出来内存容量,就可能发生颠簸。
唯一现实的解决方案就是暂时从内存中去掉一些进程。


页面大小

页面大小是操作系统可以选择的一个参数。要确定最佳页面大小要在几个矛盾的一粟直接进行权衡。从结果来看,不存在全剧最优。
某些页面没有被完全使用称为内部碎片。

页面小意味着戈多的页面,又意味着更多的页表。

内存与磁盘之间的传输一般是一次一页,传输中的大部分时间都花在了寻道和旋转延迟上,所以传输一个小的页面所用的时间和传输一个大的页面基本上是相同的。


分离的指令空间和数据空间

一种解决方法是为指令(程序正文)和数据设置分离的地址空间,分别称为I空间和D空间。
连接器必须知道何时使用分离的I空间和D空间,因为当使用他们时,数据被重定位到虚拟地址0,而不是程序之后。

在使用这种涉及的计算机中,两种地址空间都可以进行分页,而且相互独立。拥有分离的空间不会引入任何复杂设计,而且它还能使可用空间加倍。


共享页面

在共享页面中,当进程A结束时,能够发现页面依旧被使用是非常必要的。
共享数据要比共享代码麻烦,但也不是不可能。然而,所有映射到两个进程的数据页面都是只读的。

如果只是读数据,而不做修改,那么该情况可以保持下去。但只要有一个进程更新了一点数据,就会出发只读保护,而引发操作系统陷阱。然后生成一个该页但副本,这样让两个进程都有自己但专属页面。这种方法称为写时复制,可以提升性能。


共享库

任何在目标文件中调用但是没有被定义但函数都被称作为未定义外部函数。连接器会在库中寻找这些为定义外部函数。任何被这些为定义函数调用但是不存在但函数也会称为为定义外部函数。

当一个程序和共享库(与静态库存在区别)链接时,连接器没有加载被调用但函数,而是家在了一小段能够在运行时绑定被调用函数但存根历程。

当一个共享库被装载和使用时,整个哭并不是被一次性地读入内存。而是根据需要,以页面为单位装载的,因此米诶有被调用的函数是不会被加载到内存中的。


库被装载到的物理地址与这个哭是否为共享库是没有任何关系的,因为所有的页面都被MMU硬件从虚拟地址映射到物理地址。

但是由于库是共享的,因此自爱装载时在进行重定位就行不通了。
一个更好的解决方法是在编译共享库时,一个特殊的编译选项告知编译器,不要产生使用绝对地址的指令。相反,只能产生使用相对地址的指令。不论共享库被放置在虚拟地址空间的什么为止,都可以争取工作。

只使用相对便宜啦的代码称为位置无关代码。

内存映射文件

进程可以通过发起一个系统调用,将一个文件映射到其虚拟地址空间的一部分。在多数实现中,在映射共享的页面不会实际读入页面的内容,而是在访问页面时才会被每次一页的读入,磁盘文件则被当作后背存储。当进程退出或显式地接触文件映射时,所有被改动的页面会被写回文件中。

内存映射文件提供了一种IO模型的可选模型。可以把一个文件当做一个内存中的大字符串数组来访问,而不用通过读写操作来访问这个文件。

如果两个或多个进程共同易守难攻社来一个文件,他们就可以通过共享内存通信。因此,这个机制提供来一个进程之间的高带宽通道,而这种机制很普遍。(若内存映射文件可用,共享库就可以使用该机制)


清除策略

很多分页系统有一个称为分页守护进程的后台进程,它在大多数时候睡眠,但定期被唤醒以检查内存但状态。如果空闲页框锅烧,分页守护进程通过遇到但页面致幻速啊放哪选择换出内存。如果这些页面装入内存之后被修改国,则将他们写回内存。

保存一定数目但页框供给比使用所有内存并在需要时搜索一个页框有更好但性能。分页守护进程至少保证来所有空闲页框是干净的。


虚拟内存接口


允许程序员对内存映射进行控制的一个原因就是为了允许两个或者多个进程共享同一部分内存。页面共享也可以用来实现高性能的消息传递系统。



有关实现的问题

与分页有关的工作

操作系统在下面四段时间中做与分页相关的工作——进程创建时,进程执行时,缺页中断时,进程终止时。

当缺页中断发生时,操作系统必须通过读硬件寄存器来缺点时哪个虚拟地址造成缺页中断。

缺页中断处理

P128

保存信息——进行调度——使用


指令备份

到那个程序访问不在内存红的页面时,引起缺页中断的知道会半途停止并引发操作系统陷阱,在操作系统取出所需的界面后,他需要重新启动引起陷阱的指令。

但是在重新执行时不知道指令开始于何处

所以在每条指令执行之前,把程序计数器内容复制到一个隐藏的内部寄存器,用来进行指令备份

锁定内存中的页面

计算机有秀你内存并不意味着IO不起作用

一种解决方法时锁住正在做IO操作的内存中但页面保证它不会被移除内存。锁住一个页面通常称为在内存中钉住页面。另一种方法时在内河缓冲区中完成素有IO操作,然后将数据复制到用户界面


后备存储

在磁盘上分配页面空间的最简单的算法时在磁盘上功能设置特殊的交换分区,山治从文件系统划分一块独立的硬盘(以平衡IO'负载),大多数UNIX都是这么处理的。在这个分区里没有普通的文件系统,这雨就消除了将文件偏移转换成块地址的卡西奥。取而代之的时时钟使用相应分区的起始块号。

计算协会地址的过程很简单:将虚拟地址空间中的页面偏移量驾到交换去的开始地址,但在进程启动前必须初始化交换去,一种方法时将整个进程映像复制到交换去,以便随时可将所需内容装入,另一种 方法时将整个进程装入内存,并且需要时换出。

尽管程序正文通常时固定的,但数据有时会增长,堆栈页总是随时增长,这样,正文、堆栈和数据最好分贝保留交换去,并且允许这些交换去在磁盘上多于一块。

另一个极端方法时事先不分配任何东西,在页面换出时为期分配磁盘空间,并在换入时回收磁盘空间,这样内存中国年的进程不必固定于任何交换空间。但缺点在于每个进程都必须有一张表来维持。

不能保证总能事先固定的交换分区。由于程序正文通常只是只读的,当内存资源紧张,程序页不得不移出内存时,尽管丢弃即可,在需要时再从文件读入。

策略和机制的分离

控制系统复杂度的一种重要方法就是把策略从机制中国年分离出来。通过使大多数存储管理器作为用户及进程允许,就可以把该原则应用到存储管理中。

当一个进程启动时,需要通知外部页面调度程序时以便建立进程页面映射,如果需要的话还要在磁盘上分配后备存储。当进程正在运行时,它可能要把新对象映射到它的地址空间,所以还要再一次通知外部页面调度程序。

缺页中断处理程序找出需要哪个虚拟页面,并发送一条消息给外部页面调度程序告诉它发生了什么问题。


看书


分段

一个直观并且通用的方法时在机器上提供多个相互独立的称为段的地址空间。每个段由一个从0到最大的线性地址序列构成。各个段的长度可以时0到最大的现行地址序列构成。不同段的长度可以不同,通常也确实不同,段的长度可以在运行期间动态改变。

要在分段或二维存储器中指示一个地址,程序必须提供两部分地址,一个段号和一个段内地址。

段时一个逻辑实体,通常一个段内不会同时包含多种不同类型的内容。
如果随后位于段N的过程被修改并重新编译,即时新版本的程序比老版本的要打,也不需要对其它过程进行修改(因为没有修改它们的起始地址)

分段也有助于在几个进程之间共享过程和数据,最常见的例子是共享库。
这样可以让库被各个进程共享,而不必要每个进程都保留一份。

页面的内容在某种程度上是随机的,程序员甚至察觉不到分页的事实。
在分段系统中,由于用户会认为所有的段一直在内存中,也就是说它可以当作所有段都在内存中这样反问,他可以分别保护各个段,所以不需要关系覆盖他们的管理工作。

纯分段的实现

分段和分页的实现本质上是不同的,页面是定长的而段不是。



分段和分页的结合:MULTICS

如果一个段比较大,把它整保存在内存中可能很不方便甚至是不可能的,因此可以对它分页,真正需要的页面调入内存。

MULTICS:段和段内地址,段内地址又分为页号和页内的字。

分段和分页的结合:Intel Pentium

虚拟内存核心为两张表——LDT(局部描述符表)和GDT(全局描述符表)

为了访问一个段,一个Pentium程序必须把这个段的选择子装入及其的6个段寄存器的某一个总。在运行过程中,CS寄存器保存代码段的选择子,DS寄存器保存数据段的选择子。

在选择子被装入段寄存器时,对应的描述符被从LDT或GDT中取出装入为程序寄存器中,以便快速访问。一个描述符又8个字节,包括段基地址、大小和其他信息。

在禁止分页时,我们就得到一个纯的分段方案。各个段的基址在它的描述符中。另外,段指甲你允许相互覆盖。

另一方面,如果允许分页,现行地址将通过页表映射到物理地址。

每个允许程序都有一个由1024个32位表项组成的夜幕里。它通过一个全剧寄存器来定位。这个目录每个目录想指向一个包含2014个32位表项的页表。

线性地址被分为3个域:目录、页面和偏移量。目录域作为索引在也目录中找到的指向正确页表的指针,随后页面与被用作索引在也表中找到页框的物理地址,最后,偏移量被驾到页框的地址上得到物理地址。


当程序只是哟哦那个与他同级的段时,一切正常。对更高级别数据的存取是允许的,但对耕地对数据是非法对并会引起陷阱。调用不同级别代码是允许对,但要被严格控制。为执行越级调用,CALL指令必须包含一个选择子而不是一个地址。选择子只想一个调用门但描述符,由他给出调用地址。因此,跨级跳转到代码中间是不可能但,只有正式指定但入口点可以。

0级是操作系统内核,处理IO、存储管理和其它关键但操作。1级是系统调用处理程序,用户程序可以通过这里的过程执行系统调用,但只有一部分特定的和受保护的过程可以被调用。在2级是库过程,它可能是由许多正在允许的程序共享的。铜壶可以调用这些过程,读取它们的数据,但是不能修改它们。

你可能感兴趣的:(操作系统)