标签:
内存:是现代计算机运行中心。内存由很大一组字或字节组成,每个字或字节都有他们自己的地址。CPU根据程序计数器(PC)值从内存中提取指令,这些指令可能会引起进一步对特定内存地址的读取和写入。
CPU所能访问的存储器只有内存和处理器内的寄存器;
首先确保每个进程都有独立的内存空间,需确定进程可访问的合法地址的范围并确保进程只访问其合法地址。
基地址寄存器(base register):含有最小的合法物理内存地址;
界限地址寄存器(limit register):j决定范围的大小;
内存空间保护的实现,是通过CPU硬件对用户模式所产生的每一个地址与寄存器地址进行比较来来完成的。
只有操作系统可以通过特殊的特权指令来加载基地址寄存器和界限地址寄存器。(在内核模式下运行)
用户程序在执行前的处理步骤:源程序–>编译器和汇编器(编译时间)–>目标模块–>连接器(其他模块)–>加载模块—>加载器(系统库)(加载时间)–>二进制内存镜像(动态链接)(执行时间,运行时间);
在这些步骤中,地址可能有不同的表现形式。源程序中的地址通常是符号来表示。编译器通常将这些符号地址绑定(bind)在可重定位的地址。链接程序或加载程序再讲这些可重定位的地址绑定成绝对地址。每次绑定都是一个地址空间到另外一个地址空间的映射。
通常将指令与数据绑定到内存地址有一下情况:
CPU所生成的地址通常称为逻辑地址(logical adresss),而内存单元所看到的地址(即加载到内存地址寄存器(memory-adress register)中的地址) 通常称为物理地址(physical adress)。
编译和加载时的地址绑定方法生成相同的逻辑地址和物理地址,但执行时的地址绑定方案导致不同的逻辑地址和物理地址。对于这种情况,通常称逻辑地址为虚拟地址(virtual adress)。
运行时从虚拟地址到物理地址的映射是由被称为内存单元(memory-management unit,MMU)的硬件设备来完成的。
用户进程所生成的地址在交送内存之前,在将加上重定位寄存器的值才得到物理地址。
用户处理逻辑地址,内存映射硬件将逻辑地址转变为物理地址。
逻辑地址(范围为0~max),物理地址为(R+0~R+max,其中R为基地址)。
动态加载(dynamic loading):采用动态加载时,一个子程序只有在调用时才被加载。所有子程序都以可重定位的形式保存在磁盘上。主程序装入内存并执行。当一个子程序需要调用另一个子程序时,调用子程序首先检查另一个子程序是否已加载。如果没有,可重定位的链接程序将用来加载所需的子程序,并更新程序的地址表以反映这一变换。紧接着,控制传递给新加载的子程序。
动态加载的优点是不用的子程序绝不会加载。如果大多数的代码用来处理异常情况,如错误处理,那么这种方法特别有用。
动态链接库(dynamic linked library):此时系统语言库和其他目标模块一样,由加载程序合并到二进制程序镜像中。动态链接库的概念与动态加载相似,只是这里不是将加载延迟到运行时,而是将链接延迟到运行时,其不需要复制库的副本,节省空间。
共享库:在程序的链接时候并不像静态库那样在拷贝使用函数的代码,而只是作些标记。然后在程序开始启动运行的时候,动态地加载所需模块。所以,应用程序在运行的时候仍然需要共享库的支持。 共享库链接出来的文件比静态库要小得多。
进程需要在内存中以便执行,不过,进程可以短暂从内存中交换(swap)到备份存储(backing store)上,当需要再次执行时再调回内存中。
内存通常分为两个区:一个驻留操作系统(一般位于低内存),另一个用于用户进程。
通过重定位寄存器和界限地址寄存器实现。
内存分配方法:
首次适应和最佳适应都有外部碎片问题(external fragmentation):随着进程装入和移出内存,空闲内存空间被分为小片段。当所有总的可用内存之和可以满足请求,但并不连续时,这时就出现了外部碎片问题。
内部碎片:通常将内存以固定大小的块为单元来分配。进程所分配内存可能比所要的要大。这两者数字只差为内部碎片,这部分内存在分区内,但又不能用。
外部碎片解决办法:
分页(paging):内存管理方案允许进程的物理地址空间可以是非连续的。
实现分页的基本方法:将物理内存分为固定大小的块,称为帧(frame);而将逻辑内存也分为同样大小的块,称为页(page)。当需要执行进程时,其页从备份存储中调入到可用的内存帧中。备份内存也分为固定大小的块,其大小与内存帧一样。
分页硬件支持:由cpu生成的每个地址分为两部分:页号(p)和页偏移(d)。页号作为页表的索引。页表包含煤业所在物理内存的基地址,这些基地址与页偏移的组合就形成了物理地址,就可送交物理地址。
也大小(与帧的大小一样)是由硬件来决定的。页的大小通常为2的幂。512B~16MB大小不等。
分页是一种动态重定位。每个逻辑地址有分页硬件绑定为一定的物理地址。
采用分页技术不会产生外部碎片:每个帧都可以分配给需要它的进程。不过,分页有内部碎片。
分页的一个重要特点是:用户视角的内存和实际的物理内存的分离。
8.4.2 硬件支持
绝大多数操作系统都为每个进程分配一个页表。页表的指针域其他寄存器的值一起存入进程控制块中。
页表的硬件实现:将页表作为一组专用寄存器(register)来实现。这些寄存器的应用高速逻辑电路来构造,以便有效的进行分页地址的转换。
页表比较大时需将页表保存在内存中,并将页表基寄存器(page-table base),PTBR):指向页表。但问题是访问用户内存需要一些时间,即采用小但专业且快速的硬件缓冲,这种缓冲称为转换表缓冲区(translation look-aside buffer,TLB)。TLB是关联的快速内存。
TLB:TLB只包含页表中的一部分条目。当CPU产生逻辑地址时,其页号提交给TLB.如果找到页号,那么也就找到帧号,并可用来访问内存。如果页码不再TLB中(TLB失效),那么久需要访问页表。当得到帧号后就可以访问内存。同时将页号和帧号增加到TLB中,这样下次再用就可以很快查找到。
在分页的环境下,内存保护是通过与每个帧相关联的保护位来实现的。通常这些位保存在页表中。
分页的优点之一就是可以共享公共代码(可重入代码),则可共享。
分段(segmentation):支持用户视角的内存管理方案。逻辑地址空间是由一组段组成的。每个段都有名称和长度。地址指定了段名称和段内偏移(用户指定)。
段表(segment table):将二维的用户定义地址映射为一维物理地址。段表的每个条目都有段基地址和段界限。
分页和分段的区别:
虚拟内存技术允许执行进程不必完全在内存中,其显著优点是程序可以比物理内存大。而且,虚拟内存将内存抽象成一个巨大的,统一的存储数组,进而将用户看到的逻辑内存与物理内存分开。这种技术允许程序员不受内存存储的限制。
虚拟内存(virtual memory):是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
按需调页(demand paging):只有程序执行需要时才才载入页。
调页程序将那些必须的页调入内存,避免读入那些不使用的页,也减少了交换时间和所需的物理内存空间。
需要硬件支持来区分那些页在内存里,哪些页在磁盘上。
支持按需调页的硬件:
写时复制(copy-on-write):允许父进程与子进程开始时共享同一页面。且这些页面标记为写时复制页,即如果任何一个进程需要对页进程写操作,那么久创建一个共享的副本。
当确定一个页要采用写时复制是,许多操作系统为这类请求提供了空闲缓冲池。通常采用按需填零的技术以分配这些页。
UNIX :vfork(虚拟内存);vfork()会将父进程挂起,子进程使用父进程的地址空间。由于vfork()不使用写时复制,因此子进程修改父进程的地址空间的任何页,那么修改过的页在父进程重启时是可见的。vfork()主要用于在子进程被创建后立即调用exec()的情况。由于没有出现复制页面,vforK()是一种非常有效的进程创建方法,有时用于实现UNIX命令行shell的接口。
页置换:如果没有空闲帧,那么就查找当前没有使用的帧,并将其释放。可将其内容写到交换空间,并改变页表,以表示该页不在内存中。
页置换是按需调页的基础。它分开了逻辑内存与物理内存。采用这种机制,小的物理内存能为程序员提供巨大的虚拟内存。
为实现按需调页,必须解决两个问题:帧分配算法(frame-allocation algorithm)和页置换算法(page-replacement algorithm)。
页置换方法:
帧的最小数量,全局置换、局部置换;
颠簸(thrashing):频繁的页调度行为;
内存映射(memory mapping):使用虚拟内存技术奖文件I/O作为普通内存访问。
文件的内存映射可将一磁盘块映射成内存的一页(或多页)。开始的文件访问按普通页面调度来进行,会产生页错误。这样,一页大小的部分文件从文件系统读入物理页。以后文件的读写就按通常的内存访问来处理,由于是通过内存操作文件而不是使用系统调用read()和write(),从而简化了文件的访问。
通常,每个I/O控制器包括存放命令及传递数据的寄存器。专用I/O指令允许寄存器和系统内存之间进行数据传递。为了更方便的访问I/O设备,许多计算机都提供内存映射I/O。这样一组内存地址就专门映射到设备寄存器。对这些内存地址读写就如同对设备寄存器的读写。
内核内存的分配通常是从空闲内存池中获取的,而不是从满足普通用户模式进程的内存链表中获取的。主要原因如下:
对内核进程进行内存管理的两个方法:
Buddy系统:从物理上连续的大小固定的段上进行分配。内存按2的幂的大小来进行分配。及4KB,8KB,16KB等。如果请求大小不为2的幂,那么需要调整到下一个更大的2的幂。Buddy系统的一个优点是可通过合并而迅速形成更大的段。缺点是由于调整到下一个2的幂容易产生碎片。
Linux的slab可有三种状态:
slab分配器的优点:
标签:
原文地址:http://blog.csdn.net/u010177286/article/details/51602463