操作系统内存管理
静态链接是由链接器在链接时将库的内容加入 到可执行程序中的做法。链接器是一个独立程 序,将一个或多个库或目标文件(先前由编译 器或汇编器生成)链接到一块生成可执行程序。 静态链接的最大缺点是生成的可执行文件太大, 需要更多的系统资源,在装入内存时也会消耗 更多的时间。
动态链接,在可执行文件装载时或运行时,由 操作系统的装载程序加载库。大多数操作系统 将解析外部引用(比如库)作为加载过程的一 部分。
绑定
内存管理 单元(MMU)
内存管理单元(MMU)
映射虚拟地址为物理地址的硬件设备
用户进程所生成的地址在送交内存之前,都将 加上重定位寄存器(基地址寄存器)的值 用户程序决不会看到真正的物理地址
库的链接及加载
静态链接 动态链接 (dynamic link) 动态加载 (dynamic loading)
– – – – – – – –
主程序 子程序 函数 方法 对象 局部变量,全局变量 堆栈 符号表,数组
用户角度的程序
段的逻辑视角
段的体系结构
逻辑地址由两个元素组成
–
<段号,偏移>
段表:将二维的用户定义地址映射为一维物理地址。 段表的每个条目都有段基地址和段界限。
– –
基地址:包含段的起始地址 界限:指定段的长度
地址转换方法
CPU生成的地址分成以下两部分
– –
页号(p):页号作为页表中的索引。页表中包含每 页所在物理内存的基地址。 页偏移(d):与页的基地址组合就形成了物理地址, 就可送交物理单元。
地址转换体系结构
逻辑内存和物理内存的分页模型
分页示例
空闲帧
页表的实现
页表保存在内存中 页表基寄存器(PTBR)指向页表 页表长度寄存器(PTLR)指示页表的大小 在这种方式下,每次数据/指令的访问需要访问两次内 存。一次访问页表,另一次访问数据/指令 两次内存访问问题可以用特别的快速查找硬件缓冲 (称为关联内存或翻译后备缓冲器)来解决。
单分区分配方法(Single-partition allocation)
– –
重定位和界限寄存器的硬件支持
多分区分配方法
– – –
孔(Hole):一块可用内存称为孔。不同大小的孔 分布在内存的不同地方。 当有新进程需要内存时,为该进程查找足够大的孔。 操作系统维护的信息包括:
已分配分区 空闲分区(hole)
段表基地址寄存器(STBR)指向内存中的段表的位 置 段表长度寄存器(STLR)指示程序所用的段的个数
–
段号S小于STLR的时候才是有效的
段硬件
分段实例
段共享
问题
外部碎片
带分页的分段
MULTICS采用带分页的分段方法来解决外部 碎片的问题 与纯粹的分段式内存管理不同,段表的条目包 含的不是段的基地址,而是该段的页表的基地 址
内存管理
目的
详细描述内存硬件的各种组织方法 讨论各种内存管理技术,包括分页和分 段 详细描述 Intel Pentium 芯片,它支持纯 分段和带分页的分段
背景
为了运行程序必须把程序从磁盘载入到内存 内存和寄存器是CPU唯一能直接访问的存储器 寄存器的访问时间 vs 内存的访问时间
关联存储
关联内存 - 并行搜索
–
Page #
Frame #
当关联内存根据给定值查找 时,它会同时与所有键进行 比较。如果找到条目,那么 就得到相应的值域 如果A’在关联寄存器中,则 直接取出其对应的frame # 否则从内存中的页表当中得 到frame #
地址转换(A’, A’’)
– –
带TLB的分页硬件
Hash页表实例
反向页表
反向页表对于每个真正的内存页或帧才有一个 条目。 每个条目包含保存在真正内存位置的页的虚拟 地址,以及拥有该页的进程的信息。 虽然这种方案减低了存储每个页表所需要的内 存空间,但是当引用页时它增加了查找页表所 需要的时间。 可使用hash表来减少查找的次数
反向页表结构
2. 交换(swapping)
进程可以暂时从内存中交换到备份存储(backing store)上,当需 要再次执行时再调回到内存
backing store –通常是快速磁盘
优先级调度算法中使用 滚出(roll out), 滚入(roll in) 交换时间 转移时间,而转移时间与交换内存空间量成正比 问:将交换出的进程再交换(调回)回来的时候,应调回哪个内 存空间(编译时,加载时,执行时)
– –
移动内存内容,以便所有空闲空间合并成一整块。 如果重定位是动态的,是在运行时进行的,那么就能采用紧 缩
另一种可能解决外部碎片问题的方法是允许物理地址 空间为非连续,这样只要有物理内存就可为进程分配。
– –
分页 分段
分页(Paging)
一个进程的物理地址可以是非连续的 将物理内存分成固定大小的块,称为帧 (frame) 将逻辑内存分为同样大小的块,称为页 (page) 跟踪所有的空闲帧 建立页表用来将逻辑地址转换为物理地址。 内部碎片
动态存储分配问题
根据一组空闲孔来分配大小为n的请求。
–
–
–
首次适应(First-fit) 最佳适应(Best-fit) 最差适应(Worst-fit)
First-fit和best-fit在分配速度及存储效率上优于 Worst-fit
碎片(Fragmentation)
外部碎片 内部碎片 紧缩(compaction):用来降低外部碎片
–
–
页号(20位) 页偏移(12位) 10位页号 10位页偏移
页表又分成页,所以页号又进一步分成:
–
–
因此,逻辑地址表示如下
两级页表方法示意
地址转换方法
Hash页表
处理超过32位地址空间的常用方法是使用 Hash页表。 虚拟地址中的虚拟页号被放入hash页表中。 hash页表的每一条目都包括一个链接组的元 素,这些元素hash成同一位置(碰撞)。 虚拟页号与链表中的每 一个元素的第一个域 相比较。如果匹配,那么对应的帧码就用来形 成位置地址。如果不匹配,那么就对链表中的 下一个域进行页码比较。
连续分配
内存通常分为两个区域:
– –
一个用于驻留操作系统,常与中断向量一起放在低 内存 另一个用于用户进程,常放在高内存。 重定位寄存器方案用来保护用户进程之间,用户进 程与操作系统之间不会相互修改代码与数据 重定位寄存器包含了最小的物理地址;界限寄存器 包含了逻辑地址的范围,每个逻辑地址必须小于界 限寄存器
内存保护
内存保护通过与每个帧关联有保护位来实现。
–
可读、可写、只可读
还有一位与页表中的每一条目相关联,称为有效-无 效位
–
一个进程很少会使用其所有的地址空间。事实上,许多进程 只使用一小部分可用的地址空间。如
对于14位地址空间(0-16383)的系统,有一个程序,其地址空 间为0-10648
缓存
为了确保正常运行必须保护内存
首先讨论: 符号内存地址到实际物理地址的绑定 逻辑地址与物理地址的区别 动态装载、动态链接代码及共享库
在计算机科学中,库是用于开发软件的子程序 集合。库和可执行文件的区别是,库不是独立 程序,他们是向其他程序提供服务的代码。 库链接是指把一个或多个库包括到程序中,有 两种链接形式:静态链接和动态链接,相应的, 前者链接的库叫做静态库后者的叫做动态库。
基地址寄存器和界限地址寄存器
一个进程使用的内存地址范围是由一对基地址 寄存器和界限地址寄存器来定义
一个用户程序的多步骤处理
地址绑定
地址绑定是从一个地址空间到另一个地址空间 的映射 将指令与数据绑定到内存,有以下几种情况
不知道驻留地址
逻辑地址空间和物理地址空间
逻辑地址:CPU所生成的地址 –(虚拟地址) 物理地址:从内存单元所看到的地址
– –
该位有效时表示相关的页在进程的逻辑地址空间内,因此是 合法的页。 该位无效时表示相关的页不在进程的逻辑地址空间内。
页表中的有效-无效位
页表结构
层次化分页 Hash页表 反向页表
层次化分页
将逻辑地址空间分成多个页表 一种简单的方法是两层分页法
两层分页方法实例
逻辑地址(32位机器,页大小为4K)分成以 下两部分:
动态加载
直到被调用之前,程序不会被载入到内存,即 加载延迟到运行时 优点 不使用的程序不会载入到内存, 既而内存使 用率高 适合用户用大量代码来操作不常发生事件时 不需要操作系统的特别支持,由程序员来设计
动态链接
链接延迟到执行时 小程序, stub(存根), 用来定位适当的内存驻留库程 序,或如果该程序不在内存时应如何装入库 存根会用子程序地址来替换自己,并开始子程序 存根首先检查所需子程序是否在内存中,如果不在, 就将子程序装入内存。 动态链接通常适用于系统库 需要操作系统的帮助
共享页
共享代码
– –
可以在进程之间共享共同代码(只读的,可重入的) (如文本编辑器、编译器、Windows系统) 共享代码必须出现在所有进程逻辑地址的同一位置
私有代码和数据
–
–
每个进程保留了代码与数据的独立的拷贝 私有代码和数据页可以出现在逻辑地址空间的任何 地方。