《操作系统真象还原》——0.7 内存访问为什么要分段

简介: 内存按访问方式来看,其结构就如同上面的长方形带子,地址依次升高。为了解释问题更明白,我们假设还在实模式下,如果读者不清楚什么是实模式也不要紧,这并不影响理解段是什么,故暂且先忽略。

本节书摘来自异步社区《操作系统真象还原》一书中的第0章,第0.7节,作者:郑钢著,更多章节内容可以访问云栖社区“异步社区”公众号查看

0.7 内存访问为什么要分段

按理说咱们应该先看看段是什么,不过了解段是什么之前,先看看内存是什么样子,如图0-2所示。

screenshot

内存按访问方式来看,其结构就如同上面的长方形带子,地址依次升高。为了解释问题更明白,我们假设还在实模式下,如果读者不清楚什么是实模式也不要紧,这并不影响理解段是什么,故暂且先忽略。

内存是随机读写设备,即访问其内部任何一处,不需要从头开始找,只要直接给出其地址便可。如访问内存0xC00,只要将此地址写入地址总线便可。问题来了,分段是内存访问机制,是给CPU用的访问内存的方式,只有CPU才关注段,那为什么CPU要用段呢,也就是为什么CPU非得将内存分成一段一段的才能访问呢?

说来话长,现实行业中有很多问题都是历史遗留问题,计算机行业也不能例外。分段是从CPU 8086开始的,限于技术和经济,那时候电脑还是非常昂贵的东西,所以CPU和寄存器等宽度都是16位的,并不是像今天这样寄存器已经扩展到64位,当然编译器用的最多的还是32位。16位寄存器意味着其可存储的数字范围是2的16次方,即65536字节,64KB。那时的计算机没有虚拟地址之说,只有物理地址,访问任何存储单元都直接给出物理地址。

编译器在编译程序时,肯定要根据CPU访问内存的规则将代码编译成机器指令,这样编译出来的程序才能在该CPU上运行无误,所以说,在直接以绝对物理地址访问内存的CPU上运行程序,该程序中指令的地址也必须得是绝对物理地址。总之,要想在该硬件上运行,就要遵从该硬件的规则,操作系统和编译器也无一例外。

若加载程序运行,不管其是内核程序,还是用户程序,程序中的地址若都是绝对物理地址,那该程序必须放在内存中固定的地方,于是,两个编译出来地址相同的用户程序还真没法同时运行,只能运行一个。于是伟大的计算机前辈们用分段的方式解决了这一问题,让CPU采用“段基址+段内偏移地址”的方式来访问任意内存。这样的好处是程序可以重定位了,尽管程序指令中给的是绝对物理地址,但终究可以同时运行多个程序了。

什么是重定位呢,简单来说就是将程序中指令的地址改写成另外一个地址,但该地址处的内容还是原地址处的内容。

CPU采用“段基址+段内偏移地址”的形式访问内存,就需要专门提供段基址寄存器,这些是cs、ds、es等。程序中需要用到哪块内存,只要先加载合适的段到段基址寄存器中,再给出相对于该段基址的偏移地址便可,CPU中的地址单元会将这两个地址相加后的结果用于内存访问,送上地址总线。

注意,很多读者都觉得段基址一定得是65536的倍数(16位段基址寄存器的容量),这个真的不用,段基址可以是任意的。这就是段可以重叠的原因。

举个例子,看图0-2,假设段基址为0xC00,要想访问物理内存0xC01,就要将用0xC00:0x01的方式来访问才行。若将段基址改为0xc01,还是访问0xC01,就要用0xC01:0x00的方式来访问。同样,若想访问物理内存0xC04,段基址和段内偏移的组合可以是:0xC01:0x03、0xC02:0x02、0xC00:0xC04等,总之要想访问某个物理地址,只要凑出合适的段基地址和段内偏移地址,其和为该物理地址就行了。这时估计有人会问这样行不行,0xC05:-1,能这样提问的同学都是求知欲极强的,可以自己试一下。

说了这么多,我想告诉你的是只要程序分了段,把整个段平移到任何位置后,段内的地址相对于段基址是不变的,无论段基址是多少,只要给出段内偏移地址,CPU就能访问到正确的指令。于是加载用户程序时,只要将整个段的内容复制到新的位置,再将段基址寄存器中的地址改成该地址,程序便可准确无误地运行,因为程序中用的是段内偏移地址,相对于新的段基址,该偏移地址处的内存内容还是一样的,如图0-3所示。

screenshot

所以说,程序分段首先是为了重定位,我说的是首先,下面还有其他理由呢。

偏移地址也要存入寄存器,而那时的寄存器是16位的,也就是一个段最多可以访问到64KB。而那时的内存再小也有1MB,改变段基址,由一个段变为另一个段,就像一个段在内存中飘移,采用这种在内存中来回挪位置的方式可以访问到任意内存位置。

所以说,程序分段又是为了将大内存分成可以访问的小段,通过这样变通的方法便能够访问到所有内存了。

但想一想,1M是2的20次方,1MB内存需要20位的地址才能访问到,如何做到用16位寄存器访问20位地址空间呢?

在8086的寻址方式中,有基址寻址,这是用基址寄存器bx或bp来提供偏移地址的,如“mov [bx],0x5;”指令便是将立即数0x5存入ds:bx指向的内存。

大家看,bx寄存器是16位的,它最大只能表示0~0xFFFF的地址空间,即64KB,也就是单一的一个寄存器无法表示20位的地址空间——1MB。也许有人会说,段基址和段内偏移地址都搞到最大,都为0xFFFF,对不起,即使不溢出的话,其结果也只是由16位变成了17位,即两个n位的数字无论多大,其相加的结果也超不过n+1位,因为即使是两个相同的数相加,其结果相当于乘以2,也就是左移一位而已,依然无法访问20位的地址空间。也许读者又有好建议了:CPU的寻址方式又不是仅仅这一种,上面的限制是因为寄存器是16位,只要不全部通过寄存器不就行了吗。既然段寄存器必须得用,那就在偏移地址上下功夫,不要把偏移地址写在寄存器里了,把它直接写成20位立即数不就行啦。例如mov ax,[0x12345],这样最终的地址是ds+0x12345,肯定是20位,解决啦。不错,这种是直接寻址方式,至少道理上讲得通,这是通过编程技巧来突破这一瓶颈的,能想到这一点我觉得非常nice。但是作为一个严谨的CPU,既然宣称支持了通过寄存器来寻址,那就要能够自圆其说才行,不能靠程序员的软实力来克服CPU自身的缺陷。于是,一个大胆的想法出现了。

16位的寄存器最多访问到64KB大小的内存。虽然1MB内存中可容纳1MB/64KB=16个最大段,但这只是可以容纳而已,并不是说可以访问到。16位的寄存器超过0xffff后将会回卷到0,又从0重新开始。20位宽度的内存地址空间必然只能由20位宽度的地址来访问。问题又来了,在当时只有16位寄存器的情况下是如何做到访问20位地址空间的呢?

这是因为CPU设计者在地址处理单元中动了手脚,该地址部件接到“段基址+段内偏移地址”的地址后,自动将段基址乘以16,即左移了4位,然后再和16位的段内偏移地址相加,这下地址变成了20位了吧,行啦,有了20位的地址便可以访问20位的空间,可以在1MB空间内自由翱翔了。

相关文章
|
11天前
|
算法 程序员
深入理解操作系统内存管理:分页系统的优势与挑战
【4月更文挑战第7天】 在现代操作系统中,内存管理是一项至关重要的任务,它确保了计算机能够高效、安全地运行各种程序。分页系统作为内存管理的一种技术,通过将物理内存分割成固定大小的单元——页面,为每个运行的程序提供了一种独立且连续的内存地址空间。该技术不仅简化了内存分配,还允许更高效的内存使用和保护。本文探讨了分页系统的核心原理,优势以及面临的挑战,旨在为读者揭示其在操作系统设计中的重要性。
|
28天前
|
监控 安全 算法
深入理解操作系统的内存管理机制
【2月更文挑战第30天】 本文旨在探讨操作系统中至关重要的一环——内存管理。与传统摘要不同,本文将直接点出核心议题:操作系统是如何通过复杂的数据结构和算法实现对计算机内存的有效管理和优化。文章将详细阐述内存管理的关键组成部分,包括内存分配、虚拟内存技术、分页和段机制等,并探讨它们如何共同协作以支持多任务处理和保护系统安全。通过对这些机制的深入了解,读者可以更好地把握操作系统设计之精髓及对现代计算环境的深远影响。
|
28天前
|
缓存 并行计算 算法
深入理解操作系统的内存管理
【2月更文挑战第30天】 在现代计算机系统中,操作系统扮演着资源管理者的关键角色。其中,内存管理是其核心职能之一,直接关系到系统性能和稳定性。本文旨在探讨操作系统内存管理的高级概念、技术细节及其对系统运行的影响。我们将从虚拟内存的原理出发,深入分析分页机制、内存分配策略以及交换技术。文章还将讨论内存管理的优化技巧,包括最新的研究进展和未来可能的发展方向。通过本文的阐述,读者将对操作系统的内存管理有一个全面而深刻的认识。
|
28天前
|
缓存 算法 内存技术
深入理解操作系统的内存管理
【2月更文挑战第30天】 在现代计算机系统中,操作系统的内存管理是确保系统高效稳定运行的关键。本文将深入探讨操作系统中的内存管理机制,包括物理内存与虚拟内存的映射关系、分页系统的工作原理以及内存分配策略等方面。通过本文,读者可以对操作系统如何处理复杂的内存请求有一个清晰的理解,并了解如何优化内存使用以提高整体系统性能。
|
28天前
|
缓存 分布式计算 算法
深入理解操作系统的内存管理
【2月更文挑战第30天】 本文旨在探讨操作系统中的内存管理机制,通过对其核心原理的剖析和现代操作系统中内存管理技术的讨论,提供一个全面且深入的视角。文章首先概述了内存管理的基本原理,然后详细分析了分页、分段以及段页式结合等技术,并探讨了虚拟内存的概念及其在现代操作系统中的应用。最后,文章还涉及了内存管理的优化策略和未来可能的发展趋势,为读者提供了一个关于操作系统内存管理的全景视图。
|
1天前
|
存储 算法 数据安全/隐私保护
深入理解操作系统的内存管理机制
【4月更文挑战第17天】 在现代计算机系统中,操作系统扮演着资源管理者的角色,其中内存管理是其核心职能之一。本文探讨了操作系统内存管理的关键技术,包括虚拟内存、物理内存分配与回收、分页和分段机制,以及内存交换技术。通过分析这些机制的原理和实现,我们旨在加深读者对操作系统如何有效管理和保护内存资源的理解。
4 1
|
3天前
|
算法
深入理解操作系统的内存管理机制
【4月更文挑战第15天】 本文将探讨操作系统中至关重要的一环——内存管理。不同于通常对内存管理概念的浅尝辄止,我们将深入研究其核心原理与实现策略,并剖析其对系统性能和稳定性的影响。文章将详细阐述分页系统、分段技术以及它们在现代操作系统中的应用,同时比较它们的效率与复杂性。通过本文,读者将获得对操作系统内存管理深层次工作机制的洞见,以及对设计高效、稳定内存管理系统的理解。
|
10天前
|
存储 算法
深入理解操作系统内存管理:原理与实践
【4月更文挑战第8天】 在现代计算机系统中,操作系统扮演着关键角色,特别是在内存资源的管理上。本文将深入探讨操作系统中的内存管理机制,包括虚拟内存、物理内存的分配与回收,以及页面置换算法等关键技术。通过分析不同内存管理策略的优势与局限性,本文旨在为读者提供一套系统的内存管理知识框架,帮助理解操作系统如何高效、安全地管理有限的内存资源以满足多任务处理的需求。
|
14天前
|
缓存 监控 算法
深入理解操作系统的内存管理机制
【4月更文挑战第5天】 随着现代计算机系统的发展,操作系统的内存管理已成为确保系统高效稳定运行的关键因素。本文旨在探讨操作系统中内存管理的基本原理、关键技术及其在实际应用中的优化策略。通过分析内存分配、虚拟内存技术以及内存保护和分页机制等方面,揭示内存管理对提升系统性能的重要性,并提供了一系列优化内存使用效率的方法。
|
14天前
|
算法 安全
探索现代操作系统中的虚拟内存管理
【4月更文挑战第5天】 在本文中,我们深入剖析了现代操作系统中的一个关键组件——虚拟内存管理。我们将探讨其设计原理、实现机制以及它如何提升了多任务处理的效率和系统的稳定性。通过对比分析不同的内存管理策略,本文旨在为读者提供一个全面而深刻的视角,以理解虚拟内存对现代计算技术发展的重要性。