分段机制

段的定义

段的介绍

分段机制就是把虚拟地址空间中的虚拟内存组织成一些长度可变的称为段的内存单元。 80386虚拟地址空间中的虚拟地址(逻辑地址)由一个段部分和一个偏移部分构成。段是虚拟地址到线性地址转化的基础。每个段有三个参数定义:

  1. 段基地址,指定段在线性地址空间中的开始地址。基地址是线性地址对应于段中偏移 0 处。
  2. 段限长,是虚拟地址空间中段内最大可用偏移地址。定义了段的长度。
  3. 段属性,指定段的特性。如该段是否可读、可写或可作为一个程序执行,段的特权级等。

多个段映射到线性地址中的范围可以部分重叠或覆盖,甚至完全重叠,如下图所示

相关的数据结构
段的基地址、段限长以及段的保护属性存储在一个称为段描述符的结构项中。在逻辑地址到线性地址的转换映射过程中会使用这个段描述符。段描述符保存在内存中的段描述符表中。

段描述符表是包含段描述符项的一个简单数组。 使用段选择符来指定段描述符表中一个段描述符的位置来指定相应的段。

虚拟地址到线性地址转化
即使是使用段的最小功能,使用逻辑地址也能访问处理器地址空间中的每一个字节。逻辑地址由 16 位的段选择符合 32 位的偏移量组成。

当需要访问处理器地址空间中的某个字节时。段选择符指定了该字节所在的段,偏移量指定了该字节在段中相对于段基址的位置。处理器会吧每个逻辑地址转换成线性地址。线性地址是处理器线性地址空间中的 32 位地址。也是平坦的 4GB 地址空间,地址范围从 0 到 0xFFFFFFFF。线性地址空间中含有系统定义的所有段和系统表。

处理器把逻辑地址转化成一个线性地址的过程:

使用段选择符中的偏移值(段索引,我感觉这个偏移值应该是相对于段描述符表其实地址的偏移)在GDT(全局描述符表) 或 LDT(局部描述符表)中定位相应的段描述符。(仅当一个新的段选择符加载到段寄存器中时才需要 ??)

利用段描述符校验段的访问权限和范围,以确保该段是可以访问的并且偏移量位于段界限内。

利用段描述符中取得的段基地址加上偏移量,形成一个线性地址。

段描述符表

段描述符表示存放段描述符的一个数组。 它的长度可变,最多可以包含 8192 个段描述符,每个段描述符长度为 8 个字节。段描述符表有两种:全局描述符表GDT和局部描述符表LDT。段描述符表结构如下图所示。

段描述符表存储在由操作系统维护着的特殊数据结构中,由处理器的内存管理硬件来引用。 这些特殊的数据结构保存在只有操作系统能够访问的受保护的内存区域,防止被应用程序修改。

虚拟地址空间被分割成大小相等的两半。一半由GDT来映射变换到线性地址,另一半由LDT来映射。整个虚拟地址空间共含有 2^14 个段: 一般空间(2^13)是由GDT映射的全局虚拟地址空间,另一半是由LDT映射的局部虚拟地址空间。 指定一个描述符表(GDT或LDT)和表中的描述符号,就可以定位到一个段描述符(通过段描述符就可以定位到段)。

当任务切换时,LDT会更换成新任务的LDT,GDT不会改变,因为GDT所映射的一半虚拟地址空间是系统中所有任务公有的,LDT所映射的另一半则在任务切换时被改变。系统中所有任务共享的段有GDT来映射。

系统中每个应用程序对应一个任务,并且每个任务都有自己的LDT,如下图所示,应用程序A在任务A中运行,拥有LDTa ,用来映射段Codea和Dataa。类似地,应用程序B在任务B中运行,使用LDTb来映射Codeb和Datab。操作系统内核的两个段Codeos和Dataos 使用GDT来映射,这样它可以被像个人物所共享。 LDTa和LDTb两个段也使用 GDT来映射。

当任务A在运行时,可以访问 LDTa映射的Codea 和Dataa段,以及GDT映射的操作系统段COdeos和Dataos。当任务B在运行时,可以访问的段包括LDTb映射的Codeb和Datab段,以及GDT映射的操作系统段COdeos和Dataos。

通过让每个任务使用不同的LDT,演示了虚拟地址空间如何隔离每个任务。当任务A在运行时,任务B的段不是虚拟地址空间的部分。因此,任务A无法访问任务B的内存。同样的,当任务B运行时,任务A的段也不能被任务B访问。这种使用LDT来隔离每个应用程序任务的方法,正式关键保护的需求之一。

每个系统必须定义一个GDT,并可用于系统中所有程序或任务。可以选定义一个或多个LDT。可以为每个运行任务定义一个LDT,或者某些任务共享一个LDT。

GDT本身并不是一个段,而是线性地址空间的一个数据结构。GDT的基线性地址和长度必须加载进 GDTR 寄存器中。处理器并不使用 GDT中的第一个描述符。把这个"空描述符"加载到段寄存器中并不会产生一个异常。但是,如果使用这些加载了空描述符的段选择符来访问内存就会引发一般保护性异常。通过使用这个段选择符初始化段寄存器,就会引发异常。

LDT表存放在LDT类型的系统段中。此时GDT必须含有LDT的段描述符。如果系统支持多LDT,那么每个LDT都必须在GDT中有一个段描述和段选择符。一个LDT的段描述符可以存放在GDT表的任何地方。 访问LDT需使用其段选择符。为了在访问LDT是减少地址转换次数,LDT的段选择符、段基址、段限长以及访问权限需要存放在LDTR寄存器中。

段选择符

段选择符(或称段选择子)是段的一个十六位标志符,如下图所示。段选择符并不直接指向段,而是指向段描述符表中定义段的段描述符。 段选择符包括 3 个字段的内容:

  • 请求特权级RPL([0:1])
  • 表指引标志TI([2])TI = 0 ,表示描述符在GDT中,TI = 1,表示描述符在LDT中。
  • 索引值,给出了描述符在GDT或LDT表中的索引项号。

下面是一些段选择符的示例:

段描述符

每个段描述符长度是 8 字节,含有三个主要字段:段基地址、段限长和段属性。段描述符通常由编译器。链接器、加载器或者操作系统来创建,绝不可能由应用程序来创建。

段描述符通用格式如下:

原文地址:https://www.cnblogs.com/davytitan/p/12095178.html

时间: 2025-01-28 12:38:35

分段机制的相关文章

Linux内存寻址之分段机制

http://blog.xiaohansong.com/2015/10/03/Linux内存寻址之分段机制/ .段的起始地址.段的长度等等,而在保护模式下则复杂一些.IA32将它们结合在一起用一个8字节的数表示,称为描述符 .IA32的一个通用的段描述符的结构从图可以看出,一个段描述符指出了段的32位基地址和20位段界限(即段长).这里我们只关注基地址和段界限,其他的属性略过. 段描述符表 各种各样的用户描述符和系统描述符,都放在对应的全局描述符表.局部描述符表和中断描述符表中.描述符表(即段表

操作系统篇-分段机制与GDT|LDT

|| 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 在<操作系统篇-浅谈实模式与保护模式>中提到了两种模式,我们说在操作系统中,其实大部分时间是待在保护模式中的.因此若想理解操作系统程序中的启动相关的部分,必须要理解保护模式下的编程,而分段机制是保护模式编程下的基础.而且,由于实模式与保护模式的不同,对保护模式下的分段机制更需要注意. 二.线性地址 在保护模式下编程,访问内存时,需要在程序中给出段地址和偏移量,因为分段是保护模式的基本特征之一.传统上,段地址和偏移地址称为逻辑

分段机制(个人理解)

分段机制可用于实现多种系统设计.这些设计范围从使用分段机制的最小功能来保护程序的平坦模型,到使用分段机制创建一个可同时可靠地运行多个程序(或任务)的具有稳固操作环境的多段模型. 多段模型能够利用分段机制全部功能提供由硬件增强的代码,数据结构,程序和任务的保护措施.通常,每个程序(或任务)都是用自己的段描述符以及自己的段.对程序来说段能够完全是私有的,或者是程序之间共享的.对所有段以及系统上运行程序各自执行环境的访问都由硬件控制. 访问检查不仅能够用来保护对段界限以外地址的引用,而且也能用来在某些

内核保护模式之分段机制

CPU的三种模式 1982年,intel推出了80286处理器,第一次提出了保护模式,在保护模式下,段寄存器中存储的不再是段基址,而是段选择子. 真正的段基址存储在描述符高速缓存中,80286处理器访问内存,不需要段寄存器左移加上偏移. 在x86体系的CPU下,支持三种模式 实模式:兼容16位CPU的模式,当前的PC系统处于实模式(16位模式)运行状态,在这种状态下软件可访问的物理内存空间不能超过1MB,且无法发挥Intel 80386以上级别的32位CPU的4GB内存管理能力.实模式将整个物理

8086处理器为什么要采用分段机制

只要学过汇编的人都知道8086处理器对存储器采用分段管理机制,为什么要这么设计呢?采用线性地址直接访问存储器该多好,直接明了. 其实Intel的工程师绝对不会那么傻,当然是有他的道理: 首先,地址总线有20根,可寻址1M的地址空间,而寄存器是16位,仅能寻址64K,总不能白白浪费多出来的空间.要知道在8086的那个年代,内存是非常昂贵的. 所以Intel的工程师想出了分段管理的方法:段地址x4+偏移地址. 另外,分段管理还有利于代码的组织,对内存实现有效的管理.例如,将代码段.数据段隔离等. 学

通过分段机制和分页机制实现禁止数据写入

今天调试程序的时候,对windows对R3的保护机制很感兴趣,为什么rdata段只可读,为什么data可读写,为什么text段不可写入,只可执行,正好今天没事干,这里就做了个测试,首先查看程序断到入口点后,它的物理页的情况 kd> !dd 1db69000 #1db69000 120a5025 80000000 1e642025 00000000 #1db69010 03481025 80000000 1e85e225 80000000 #1db69020 1db96025 80000000 0

Linux的分段和分页机制

1 基于80x86的Linux分段机制 80386的两种工作模式:80386的工作模式包括实地址模式和虚地址模式(保护模式).Linux主要工作在保护模式下. 在保护模式下,80386虚地址空间可达16K个段,每段大小可变,最大达4GB.逻辑地址到线性地址的转换由80386分段机制管理.段寄存器CS.DS.ES.SS.FS或GS各标识一个段.这些段寄存器作为段选择器,用来选择该段的描述符. 分段逻辑地址到线性地址转换图: Linux对80386的分段机制使用得很有限,因为Linux的设计目标是支

实模式与保护模式下的分段分页机制

1. 实模式 在实模式下,CPU不会为任务提供任务的保护机制,代码任意运行.8086处理器是学习实模式的常用例子.它内部大致有以下寄存器: 8个16位的通用寄存器: AX (可以拆分成两个AH/AL的8位寄存器) BX (BH,BL) CX (CH,CL) DX (DH,DL) SI (source index, 源索引寄存器) DI (destination index, 目的索引寄存器) BP (base pointer, 基数指针寄存器) SP (stack pointer, 堆栈指针寄存

Linux的内存管理机制

内存管理的一些基本概念: 地址 1)逻辑地址:指由程序产生的与段相关的偏移地址部分.在C语言指针中,读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址. 2)线性地址:段中的偏移地址(逻辑地址),加上相应段的基地址就生成了一个线性地址. 3)物理地址:放在寻址总线上的地址. 4)虚拟地址:保护模式下段和段内偏移量组成的地址,而逻辑地址就是代码段内偏移量,或称进程的逻辑地址. 内存管理主要解决以下问题: 进程的地址空间隔离: 提高内存的使用效率: 程序运行时重