目录
基址极限寄存器(Base and Limit Registers)
一、内存管理
内存管理是操作系统中一个非常重要的功能,它主要负责管理计算机系统中的内存资源,包括内存的分配、回收、保护和共享等。下面简要介绍内存管理的几个关键方面:
-
内存分配:
- 内存分配是指在程序运行时为程序分配所需的内存空间。常见的内存分配方式包括连续内存分配和离散内存分配。连续内存分配将整个内存空间划分为若干连续的区域,每个区域都有固定的大小;离散内存分配则将内存空间划分为多个不相连的小块,根据程序的需求进行动态分配。
-
内存回收:
- 内存回收是指在程序运行结束或者不再需要某块内存时,将该内存释放出来以供其他程序使用。内存回收的方式包括手动回收和自动回收。手动回收需要程序员显式地释放内存,而自动回收则由系统自动管理,例如自动垃圾回收机制。
-
内存保护:
- 内存保护是指防止程序越界访问内存、修改其他进程的内存等非法操作的机制。常见的内存保护方式包括基址限址寄存器(Base and Limit Register)、分页管理、分段管理等。
-
内存共享:
- 内存共享是指多个进程之间共享同一块内存空间的机制。内存共享可以提高系统资源的利用率和进程之间的通信效率。常见的内存共享方式包括共享内存、消息队列、信号量等。
-
内存碎片:
- 内存碎片是指未被有效利用的内存空间,包括内部碎片和外部碎片。内部碎片是指分配给进程的内存空间中未被使用的部分;外部碎片是指已被分配但无法被其他进程使用的内存空间。
-
虚拟内存:
- 虚拟内存是一种将磁盘空间作为扩展内存的技术,可以将部分程序或数据从内存交换到磁盘上,以提高系统的性能和可用性。虚拟内存通过页面置换算法实现内存的动态分配和回收。
二、内存管理的环境
不同的操作系统有不同的内存管理机制和策略,下面介绍一下常见的几种:
-
分段式内存管理:
- 实现原理:将程序的代码、数据、堆栈等分成若干个段,每个段对应一个物理内存块,通过段号和段内偏移量来寻址。
- 特点:易于实现共享和保护,但会产生内存碎片,不适合动态内存分配。
-
分页式内存管理:
- 实现原理:将程序划分为若干个大小相等的页面,存储到物理内存中,通过页表将逻辑地址映射到物理地址。
- 特点:灵活、紧凑,可以支持动态内存分配和共享,但需要频繁地进行页面置换,可能会导致性能损失。
-
段页式内存管理:
- 实现原理:将程序先划分成若干个段,再将每个段划分为若干个大小相等的页面,采用二级页表映射逻辑地址到物理地址。
- 特点:综合了分段式和分页式的优点,既可以实现保护和共享,又可以支持动态内存分配和页面置换。
-
可变分区式内存管理:
- 实现原理:将内存划分为多个大小不同的区域,每个区域可以用于存储一个进程,支持动态内存分配和释放。
- 特点:灵活、高效,但容易产生外部碎片,需要采用内存回收算法进行优化。
三、虚拟内存
虚拟内存是一种计算机系统的内存管理技术,它将磁盘空间用作临时存储器,并根据需要在RAM(随机存取存储器)和磁盘之间来回传送数据。虚拟内存的实现原理和优缺点如下:
实现原理:
- 当程序需要访问某个内存地址中的数据时,操作系统会先检查这部分数据是否已经在物理内存中,如果是,则直接访问;如果不在,操作系统会将这部分数据从磁盘中调入物理内存,同时将不常用的数据移到磁盘上,从而腾出空间。这个过程是透明的,对于应用程序来说,似乎所有数据都存储在物理内存中。
优点:
- 提高系统性能:虚拟内存可以扩展可用的地址空间,允许运行更大的程序或者多个程序同时运行,从而提高系统的性能。
- 简化内存管理:虚拟内存可以提供对物理内存的抽象,使得程序可以使用比实际物理内存更大的内存空间,简化了内存管理的复杂性。
- 增加程序的运行稳定性:虚拟内存可以实现内存保护和内存共享,减少因为程序错误导致系统崩溃的可能性。
缺点:
- 性能开销:由于虚拟内存需要频繁地进行磁盘和内存之间的数据交换,可能会导致性能损失。
- 复杂性:虚拟内存的实现相对复杂,需要考虑页面置换算法、页面错误处理等问题,增加了系统的复杂性。
- 磁盘空间占用:虚拟内存需要占用一部分磁盘空间作为交换空间,可能会导致磁盘空间的浪费。
应用场景: 虚拟内存广泛应用于现代操作系统中,特别是在多任务操作系统和服务器系统中。它使得系统能够更加高效地管理内存,支持多任务并发执行,提高系统的稳定性和性能。在需要运行大型程序或者多个程序并发执行的场景下,虚拟内存能够发挥其作用,确保系统的正常运行。
四、操作系统在内存中的位置
操作系统在内存中的位置取决于具体的操作系统和硬件平台。通常,操作系统会被加载到计算机的物理内存中,并占用一定的地址空间。在x86架构的计算机上,通常将操作系统加载到内存地址0x0000 0000 ~ 0xFFFF FFFF的范围内。
具体地说,操作系统通常会被分成多个模块,例如内核、驱动程序、文件系统等,每个模块都需要被加载到内存中并占用一定的地址空间。操作系统内核通常会被加载到内存的最高地址部分,这样可以让操作系统能够访问整个物理内存空间。其他模块则会被加载到较低的地址部分,并根据需要进行分页或虚拟地址映射等处理。
在操作系统启动时,BIOS会首先加载启动引导程序(Boot Loader)到内存中,并将控制权传递给引导程序。引导程序再负责加载操作系统内核和其他模块到内存中,并进行一系列初始化和配置操作,最终将控制权交给操作系统内核。
五、程序在内存中的位置
程序在内存中的位置取决于具体的加载方式和内存管理策略。常见的程序加载方式有固定加载地址、固定分区和可变分区。
1.固定加载地址
在固定加载地址的情况下,程序被加载到内存的固定地址上,程序执行时其所有部分都位于该地址范围内。这种方式可以简化程序的链接和重定位,但是会限制系统中其他程序和模块占用内存的位置。这种方式通常适用于嵌入式系统等对内存资源要求较为严格的场景。
2.固定分区
在固定分区的情况下,操作系统将内存划分为若干个固定大小的分区,每个分区用于存储一个程序或模块。程序被加载到其所属的分区内,程序执行时只能访问该分区内的内存空间。这种方式可以提高内存利用率和安全性,但是会造成内存碎片和浪费,同时也限制了程序的灵活性。
3.可变分区
在可变分区的情况下,操作系统将内存划分为若干个可变大小的分区,每个分区用于存储一个程序或模块。程序被加载到可用的分区内,并可以动态调整所占用的内存空间。这种方式可以提高内存利用率和灵活性,但同时也增加了内存管理的复杂度。
需要注意的是,现代操作系统通常采用虚拟内存技术,将程序的逻辑地址映射到物理地址上。在这种情况下,程序的逻辑地址空间被划分为若干个页面(Page),每个页面被映射到内存中的一个物理页面框(Page Frame)。程序执行时,只有当前需要的页面会被加载到内存中,并进行访问。这种方式可以提高内存利用率和安全性,同时也增加了内存管理的复杂度。
六、页面置换算法
这里介绍三种页面置换算法:随机算法、先进先出算法和最近最少使用算法(LRU算法)
-
随机算法
- 概念:从内存中随机选择一个页面进行替换。
- 实现机制:通过随机数生成器随机选取一个页面进行替换。
- 优点:实现简单,适用于某些特殊的场景。
- 缺点:不能保证替换掉的页面是最不常用的,可能会导致性能损失。
- 应用场景:不需要考虑性能问题的场景,如某些单机应用场景。
-
先进先出算法(FIFO)
- 概念:将最早进入内存的页面替换出去。
- 实现机制:维护一个队列,记录所有进入内存的页面的顺序,替换掉队首的页面。
- 优点:实现简单,易于理解。
- 缺点:无法反映页面的访问频率,可能会导致“老旧页面”频繁替换,影响性能。
- 应用场景:不需要考虑页面访问频率的场景,如某些嵌入式系统。
-
最近最少使用算法(LRU算法)
- 概念:替换最长时间未被使用的页面。
- 实现机制:维护一个访问页面时间的链表,最近访问的页面排在链表前面,替换掉链表尾部的页面。
- 优点:能够反映页面的访问频率,可以更好地保留常用页面,提高性能。
- 缺点:实现较为复杂,需要维护访问时间链表。
- 应用场景:对于频繁访问同一页面的场景,LRU算法能够比其他算法更好地发挥作用,如大型数据库和读取磁盘文件的应用。
示例
假设我们有一个缓存大小为4的LRU缓存,并且我们使用双向链表来维护页面的访问顺序。
-
初始化缓存和双向链表为空,并创建一个哈希表用于快速查找页面。
-
当访问页面A时,首先在哈希表中查找A是否存在于缓存中:
- 如果存在,将页面A从双向链表中移动到链表的头部,表示A是最新访问的页面。
- 如果不存在:
- 如果缓存已满,需要进行页面替换。将链表尾部的页面替换出去,并从哈希表中删除该页面的记录。
- 将页面A添加到缓存的头部,并在双向链表和哈希表中添加相应的记录。
-
当再次访问页面B时,重复步骤2的操作。
-
当访问页面C时,重复步骤2的操作。
-
当再次访问页面A时,由于页面A已经存在于缓存中,需要将页面A从链表中移动到头部,表示A是最新访问的页面。
-
当访问页面D时,重复步骤2的操作。
通过这种方式,双向链表可以根据页面的访问顺序进行排序,最近访问的页面始终位于链表的头部,而最久未使用的页面位于链表的尾部。哈希表用于快速查找页面是否在缓存中,并且可以在O(1)时间内完成。
七、内存管理方式
在操作系统中,常见的内存管理方式包括以下几种:
1.连续内存分配
单一连续区域分配
将整个内存空间划分为一个连续的区域,用于存放进程。
- 概念:将整个内存空间划分为一个连续的区域,用于存放一个进程。进程在内存中占据一段连续的地址空间。
- 实现机制:根据进程的大小和内存空闲情况,在内存中找到一块足够大的连续空间,将进程加载到这个空间中。
- 优点:实现简单,适合于固定大小的进程,没有外部碎片。
- 缺点:易产生内部碎片,浪费内存空间;不利于动态分配和回收内存。
- 应用场景:适用于固定大小的进程,如嵌入式系统中的固定功能模块。
分区分配
将内存空间划分为若干个固定大小的分区,每个分区用于存放一个进程。
- 概念:将内存空间划分为若干个固定大小的分区,每个分区用于存放一个进程。每个分区可以被分配给一个进程,也可以是空闲状态。
- 实现机制:维护一个分区表,记录每个分区的使用情况和进程ID,根据请求的大小选择合适的分区进行分配。
- 优点:能够有效减少内部碎片,支持多个进程并发执行。
- 缺点:可能产生外部碎片,空闲分区的管理复杂;难以满足动态内存需求。
- 应用场景:适用于多道程序设计环境,如操作系统中同时运行多个用户程序的场景。
动态分区分配
根据进程的大小动态划分内存空间,可以灵活利用内存资源。
- 概念:根据进程的大小动态划分内存空间,每个进程所需的内存大小不固定,可以根据需要进行调整。
- 实现机制:使用动态分配算法(如首次适应、最佳适应、最坏适应)来选择合适的空闲分区进行分配。
- 优点:灵活性高,能够更好地利用内存资源,减少外部碎片。
- 缺点:算法复杂,可能导致碎片问题;容易产生内存碎片,影响内存利用率。
- 应用场景:适用于需要动态管理内存空间的系统,如通用计算机操作系统中的内存管理。
2.非连续内存分配
分段管理系统
将程序划分为若干个逻辑段,每个段有自己的长度和基址,提高程序模块化和可维护性。
- 概念:将程序划分为若干个逻辑段,每个段代表程序中的一个逻辑单元,如代码段、数据段等,每个段都有自己的长度和基址。
- 实现机制:通过段表来映射逻辑地址到物理地址,段表中存储每个段的基址和界限信息。
- 优点:易于实现程序模块化,支持共享和保护,提高程序的可读性和维护性。
- 缺点:容易产生内部碎片,不利于动态内存分配,段的大小不一致可能导致空间浪费。
- 应用场景:适用于多道程序设计环境,如操作系统和编程语言的运行时环境。
分页管理系统
将程序划分为固定大小的页面,将物理内存划分为相同大小的页框,适应虚拟内存系统。
- 概念:将程序划分为固定大小的页面(page),将物理内存划分为相同大小的页框(frame),逻辑地址和物理地址均以页为单位。
- 实现机制:通过页表来映射逻辑页面到物理页面,页表记录了每个逻辑页面映射到的物理页面的地址。
- 优点:实现简单,减少了外部碎片,支持动态内存分配,适应性强。
- 缺点:可能会产生页面置换开销,页表过大会影响查找速度。
- 应用场景:适用于虚拟内存系统,支持程序的动态加载和分页式存储管理。
3.虚拟内存管理
基于分页的虚拟内存
通过将主存和磁盘空间结合起来,实现了虚拟内存的概念,支持程序的动态加载和分页式存储管理。
- 概念:基于分页的虚拟内存是一种内存管理技术,它通过将程序的地址空间划分为固定大小的页面,并将物理内存也划分为相同大小的页面,实现了程序的动态加载和分页式存储管理。
- 实现机制:当程序执行时,只有部分页面需要装入内存,其余部分暂时存储在磁盘上。当程序访问未装入内存的页面时,操作系统会触发缺页中断,将需要的页面从磁盘调入内存并更新页表。
- 优点:支持程序的动态加载和虚拟化存储管理,节约内存空间,提高进程的并发度和系统的性能。
- 缺点:增加了访问内存的开销,可能引起性能损失;需要合理的页面置换算法来管理内存。
- 应用场景:通用计算机操作系统中广泛应用,支持多任务处理和大型程序的执行。
页面置换算法
在虚拟内存系统中,由于内存空间有限,需要使用页面置换算法来决定哪些页面被置换出去,常见的算法包括LRU、FIFO等。
- 概念:页面置换算法用于在内存中选择哪些页面被替换出去,以便为即将调入的页面腾出空间。常见的算法包括最近最少使用(LRU)、先进先出(FIFO)、最不常用(LFU)等。
- 实现机制:根据页面的访问情况和优先级,选择合适的页面进行置换,保证内存中总是保存着对当前执行有用的页面。
- 优点:可以有效地提高内存利用率,减少页面置换的开销。
- 缺点:不同的算法适用于不同的场景,难以找到一种适用于所有情况的通用算法。
- 应用场景:在需要虚拟内存管理的系统中广泛应用,如桌面操作系统、服务器操作系统等。
4.段页式管理系统
结合了分段管理和分页管理的优点,既支持程序模块化又支持虚拟内存系统,适应性更强。
- 概念:段页式管理系统是一种将程序的地址空间划分为多个段,每个段再划分为多个页的内存管理技术。它克服了分段和分页各自的局限性,结合了两者的优点,提供了更灵活、高效的内存管理方案。
- 实现机制:程序的逻辑地址由段号和页号组成,首先根据段号找到对应的段表项,然后再根据页号找到对应的页表项,最终计算出物理地址。这样一来,程序的地址空间被划分为多个不同大小的段,每个段再被划分为固定大小的页,实现了灵活的内存管理。
- 优点:支持非连续内存分配,提高了内存的利用率;兼顾了分段和分页的优点,更加灵活,能够满足不同程序的内存需求。
- 缺点:实现复杂,需要管理段表和页表,增加了内存访问的开销;可能产生内部和外部碎片。
- 应用场景:适用于需要灵活管理程序地址空间的系统,如操作系统内核、服务器操作系统等。
八、内存管理机制
基本内存管理机制包括地址翻译、基址极限寄存器和交换。这些机制是操作系统用于管理进程内存访问的重要工具。
地址翻译(Address Translation)
- 地址翻译是指将程序中的逻辑地址(或虚拟地址)转换为对应的物理地址的过程。在现代计算机系统中,通常使用硬件支持的地址翻译机制(如MMU,Memory Management Unit)来实现虚拟内存管理。当程序访问内存时,逻辑地址首先经过地址翻译,然后被映射到物理地址上,从而实现了对物理内存的访问。
基址极限寄存器(Base and Limit Registers)
- 基址极限寄存器是一种内存保护机制,用于限制进程访问的内存范围。基址寄存器存储进程的起始地址(基址),而极限寄存器存储进程可以访问的内存空间大小(极限)。当程序访问内存时,硬件会检查逻辑地址是否在基址和基址+极限之间,以确保程序只能访问其分配的内存空间。
交换(Swapping)
- 交换是指将进程暂时地移出内存,以便为其他进程腾出空间的操作。当系统内存不足时,操作系统可以将部分进程的内容换出到磁盘上,以释放内存空间供其他进程使用。被换出的进程称为“交换出去”,而换入内存的进程称为“交换回来”。交换操作需要进行频繁的磁盘I/O,因此会带来一定的性能开销。
这些基本内存管理机制在操作系统中扮演着重要的角色,它们可以帮助操作系统有效地管理内存资源,并实现进程的内存隔离和保护。同时,这些机制也对系统的性能和效率产生了一定的影响,因此在设计和实现操作系统时需要综合考虑各种因素,以达到平衡的目标。
九、闲置空间管理
操作系统中的闲置空间管理是指如何处理内存中的空闲区域,以便能够更有效地利用内存资源。常见的闲置空间管理技术包括分区管理、页表组织和伙伴系统。
分区管理
- 分区管理是一种将内存划分为固定大小的区域的方法。每个区域被分配给一个进程,进程只能访问自己的区域。当一个进程终止时,其所占用的区域将被标记为空闲状态,以便下一个进程可以使用。这种方法可以简单地实现内存管理,但是会造成内存碎片和浪费。
页表组织
- 页表组织是一种将内存划分为可变大小的页面的方法。当一个进程需要内存时,它可以请求一定数量的页面。操作系统在内存中找到足够数量的连续页面,并将它们分配给进程。当进程结束时,这些页面将被释放,并标记为空闲状态。这种方法可以避免内存碎片和浪费,但是会增加内存管理的复杂度。
伙伴系统
- 伙伴系统是一种高效的闲置空间管理技术。它将内存分成不同的大小等级,并使用一个伙伴系统来管理这些等级。当一个进程需要内存时,操作系统会找到一个与请求大小最接近的空闲页面,并将其分配给进程。如果该页面的大小大于所需大小,操作系统会将页面一分为二,并将其标记为伙伴关系。这种方法可以避免内存碎片和浪费,并提高内存利用率。
十、内存抖动
内存抖动是指系统中频繁发生内存页面置换的现象,这可能会导致系统性能下降。内存抖动通常发生在系统内存不足时,导致操作系统频繁地将页面从物理内存中换出到磁盘(页面置换),而后又需要将其重新调入内存,这样频繁的置换操作会消耗大量的计算资源和时间,影响系统的性能。内存抖动通常是由于以下原因导致的:
-
内存不足:系统中的可用内存不足,无法同时容纳所有需要运行的程序和数据,导致频繁的页面置换操作。
-
内存分配不合理:部分程序可能分配了过多的内存,或者内存分配的方式不够高效,导致系统整体的内存利用率不佳。
-
工作负载波动:系统中的工作负载出现了剧烈波动,导致原本合理的内存管理策略无法满足新的需求,从而产生内存抖动。
解决内存抖动的方法通常包括以下几个方面:
-
增加物理内存:通过增加系统的物理内存大小,可以减少内存抖动的发生,提高系统的性能。
-
优化内存分配策略:对程序的内存使用进行优化,包括释放不再需要的内存、使用更高效的内存分配算法等。
-
调整页面置换策略:选择更适合当前工作负载的页面置换算法,以减少页面置换的开销。
-
优化工作负载:合理调整系统的工作负载,避免出现剧烈的波动,降低内存抖动的发生频率。
总之,内存抖动是系统中的一种性能问题,需要通过增加物理内存、优化内存分配策略、调整页面置换策略和优化工作负载等手段来进行解决,以提高系统的稳定性和性能。