逻辑地址是由应用程序生成的地址,也称为虚拟地址。它是程序中使用的地址,与实际的物理内存位置无关。逻辑地址是相对于进程的地址空间而言的。
在保护模式下,每个进程都有自己的逻辑地址空间,这使得每个进程可以使用相同的逻辑地址,而不必担心与其他进程的地址冲突。逻辑地址由段选择符和偏移量组成。
线性地址是逻辑地址到物理地址之间的中间层,也称为虚拟地址。在保护模式下,逻辑地址通过分段机制和分页机制映射到线性地址。
每个进程的线性地址空间都从零开始,然后通过分段机制进行映射到逻辑地址空间。线性地址与逻辑地址之间的映射由段描述符(Segment Descriptor)控制。
物理地址是内存中存储数据的实际地址,也称为真实地址。物理地址是RAM芯片上的特定位置。
线性地址通过分页机制映射到物理地址。分页机制将线性地址划分为固定大小的页面,并将这些页面映射到物理内存中的页面帧上。
逻辑地址到线性地址的转换:
首先,逻辑地址通过段选择符查找相应的段描述符。段描述符中包含了段的基地址。
然后,将逻辑地址的偏移量添加到段的基地址,得到线性地址。
线性地址到物理地址的转换:
线性地址通过页表(Page Table)或页目录表(Page Directory)进行映射到物理地址。
分页机制将线性地址分成页面(通常大小为4KB或2MB),并通过查找页表或页目录表,将每个页面映射到物理内存中的一个页面帧。
在基本平坦模型中,系统只使用单一的段,通常称为平坦段(Flat Segment),所有的逻辑地址都映射到相同的线性地址空间。这个模型忽略了分段机制的复杂性,将整个内存视为一个连续的地址空间,适用于非常简单的操作系统或嵌入式系统。这种模型的好处是简单,但不具备内存隔离和保护的特性。
在保护平坦模型中,仍然使用单一的段,但借助保护模式和特权级别的概念,提供了更高级的内存保护和隔离。每个进程都有自己的线性地址空间,不同进程之间的地址不会冲突。操作系统可以使用分页机制来实现虚拟内存管理,将线性地址映射到物理地址,并提供内存隔离。这是现代操作系统(如Windows、Linux)的常用模型。
多段模型允许使用多个不同的段来管理内存。每个段可以有自己的基地址和大小,用于存储不同类型的数据或代码。这个模型在早期的x86系统中常见,但在保护模式引入后逐渐被弃用。在多段模型中,需要维护多个段描述符,并且需要在不同段之间进行切换,增加了管理的复杂性。
段选择子是一个16位的值,用于在GDT(全局描述符表)或LDT(局部描述符表)中选择一个段描述子。段选择子包括两部分:索引(Index)和请求特权级别(Requested Privilege Level,RPL)。
x86架构中有一些段寄存器,包括CS(Code Segment,代码段寄存器)、DS(Data Segment,数据段寄存器)、ES(Extra Segment,附加段寄存器)、SS(Stack Segment,堆栈段寄存器)等。这些寄存器存储了段选择子的值,用于指示当前正在访问的段。
段描述子是GDT或LDT中的数据结构,用于描述一个段的属性。一个段描述子包括段的基地址、段的大小、段的特权级别、类型等信息。每个段寄存器都指向一个段描述子,以确定如何访问这个段。
应用程序生成一个逻辑地址,它通常由段选择子和偏移量组成。
处理器通过段选择子来确定要访问的段描述子。它首先检查段选择子中的索引,然后根据请求特权级别(RPL)来决定是在GDT还是LDT中查找段描述子。
一旦找到了段描述子,处理器提取其中的基地址(Base Address)并将其与逻辑地址中的偏移量相加,得到线性地址。
线性地址可以用于后续的内存访问,但仍然需要经过分页机制的映射,最终才能得到物理地址。
数据段描述符用于定义内存中的数据段的属性,如数据段的基地址、大小、特权级别、访问权限等。数据段描述符允许程序访问和操作数据。
代码段描述符用于定义内存中的代码段的属性,如代码段的基地址、大小、特权级别、访问权限等。代码段描述符允许程序执行指令。
局部描述符表描述符用于描述局部描述符表(LDT)的属性。每个进程可以有自己的LDT,它包含了进程特定的段描述符。
任务状态段描述符用于定义任务状态段(TSS)的属性。TSS包含了处理器在任务切换时的状态信息,如通用寄存器、段寄存器、堆栈指针等。
调用门描述符用于定义调用门的属性。调用门允许程序从一个特权级别跳转到另一个特权级别,同时进行特权级别的切换。
中断门描述符用于定义中断门的属性。中断门允许处理器响应中断事件,进行中断处理,同时进行特权级别的切换。
陷阱门描述符用于定义陷阱门的属性。陷阱门类似于中断门,但不会关闭中断响应标志,允许陷阱处理程序嵌套执行。
任务门描述符用于定义任务门的属性。任务门允许程序从一个任务跳转到另一个任务,进行任务切换。