操作系统中的段描述符

2025年1月7日 | 阅读 12 分钟

一种称为分段的内存处理技术,用于进程划分为离散块或段的虚拟内存。通过这种数字代码,每个段都将具有唯一的标识,并具有防止未经授权访问的保护系统。与分页相比,分段更灵活、更强大,因为它增加了通过将现有不同大小的单元连接成逻辑单元来形成更大块的能力。

分段是一种将内存分配给进程的各部分的技术。这意味着进程的地址空间被划分为多个段,这些段根据它们在系统中的角色进行区分。每种类型包含执行环境的各个部分,其中包含应用程序代码、数据、堆栈、堆或其他由最终用户控制的类型。段名称/段号将每个部分分开,并显示其起始地址和长度。这种机制表明系统以不同的方式获取内存,因为程序在处理器中是分开管理的,并且系统决策过程有更多的时间。它可能涉及特殊区域,例如用于可执行代码、数据和实例的扇区,其中为每个句柄提供了不同的访问权限和保护集。

段描述符简介

段描述符是一个需要定义的对象,用于表示内存段的属性,这对操作系统访问至关重要。由于其结构,它有一个包含几个字节的开头,用于标识段、其限制大小、特权级别和其他一些控制位。段描述符的主要目的是保证页面内存地址的安全以及访问控制规则的实施。

段描述符的组成部分

段描述符的几个组成部分如下:

  • 基地址:需要基地址来显示正在使用的物理内存中的内存段的位置。它指向地址总线上的特定位置。在其他情况下,它标识包含数据或指令的内存位置。
  • 限长:限长指定内存段的大小,并定义段内有效地址的范围。它防止程序访问超出规定限长的内存,从而确保内存保护。
  • 访问权限:与该段相关的特权,例如读、写、执行和段类型(代码、数据或系统),将定义为访问权限。通过这些权限,进程可以限制段与进程交互的能力,同时也有助于建立安全策略。
  • 段类型:段类型解释了段的性质,是用于指令、数据、堆栈还是系统信息。
  • 描述符类型:此段描述符类型指定该段是指系统段还是数据/代码段。系统模块将参与核心功能,例如中断处理,而代码/数据段将保存程序指令或数据。
  • 特权级别:请求者特权级别(RPL)限制用户试图请求的段的访问级别。它有助于系统中的保护,这是一项使进程只能访问具有应有权限和安全性的段的功能。
  • 存在位:此位表示两种情况之一,即数据段是否在内存中(存在)。如果源代码片段完好无损,尝试访问该代码片段将导致称为段错误(segmentation fault)的错误。
  • 描述符表指示符:全局描述符表(GDT)和局部描述符表(LDT)由此字段表示,它指定段描述符位于其中一个表中。在访问内存时,它有助于搜索和定位最合适的描述符表。

段的类型

段是用于系统管理和内存组织的方案的重要组成部分。它们提供了一种内存管理技术,在一个内置结构中,将进程的地址空间划分为具有不同目的的各个部分。

  • 代码段:代码段,通常称为文本段,包含程序的执行指令。它存储由编译器或汇编器生成的机器码,通常是只读的。代码段存储 CPU 执行的程序的逻辑和指令。
  • 数据段:主内存段包括数据、堆栈和代码。数据空间存储程序的已初始化全局变量和静态变量。它包含声明并带有初始化值的选项,这些值在源代码编译时分配。用于数据访问的段是可写的。因此,程序可以在运行时更改给定的变量值。R 顺序内存也分为两部分:已初始化数据(用特定值初始化)和未初始化数据(初始化为零或空值)。它也称为BSS(块以符号开始)
  • 堆栈段:堆栈段是与内存的动态分配和函数调用期间的堆栈管理相关的内存段。它保存属于局部变量、函数参数、返回地址以及任何其他与函数相关的详细信息的处理器数据。堆栈遵循 LIFO(后进先出)原则,这意味着最近推入堆栈的项目是第一个被弹出。在程序运行时,堆栈段是动态增长和缩小的,通常从较高的地址开始并向下减少。
  • 系统段:操作系统不使用或占用地址总线上的所有地址。相反,系统段由操作系统用于管理系统资源和执行特权指令。这些段包括中断描述符表(IDT)、任务状态段(TSS)和其他系统相关结构。在 IDT 中,存在中断或异常处理程序,而在 TSS 上下文中,则执行任务状态存储。TSS(任务状态段)是一个用于多操作系统中任务状态和上下文切换的技术段。
  • 应用程序段:除了常规的堆栈、数据和代码段外,还可以添加标准应用程序不需要的新段。这些场景包括但不限于多媒体数据段、动态库、用户定义数据结构或任何专用数据或代码。处理这些功能的应用程序部分有助于以简化的方式运行,并优化内存使用和资源利用。

段描述符表

段描述符表(SDT)是内核用于优化段描述符的数据结构。此存储库将充当段描述符的中央文件,并使操作系统能够有效地管理内存、保护内存并执行与分段相关的操作。

全局描述符表 (GDT)

全局描述符表(GDT)是一个全面的系统表,包含供整个系统和应用程序环境使用的段描述符。它是包含可供所有进程访问的内存段的内存结构。它们通常在各个进程之间共享。GDT 从系统启动时开始工作,并在整个系统生命周期内保持不变。它确实具有内存分段的全局视图,这对于建立内存保护策略和访问控制至关重要。

局部描述符表

局部描述符表(LDT)是一个段描述符表。它与特定进程和应用程序相关。每个进程都可以拥有自己的 LDT,并定义具有传统技术无法比拟的特定内存段的访问权限和特权。LDT 作为 GDT 的补充,能够更精细地控制和分段内存访问和保护组。同时,随着更复杂的内存管理过程的引入,片上 LDT 的使用已大大减少。

任务状态段 (TSS)

任务状态段(TSS)是多操作系统中用于切换任务状态和上下文的技术段。它可以保存当前线程的历史信息,通常包括 CPU 寄存器、堆栈指针和其他程序执行相关数据。CPU 在切换任务时使用 TSS 来存储 CPU 的状态,并在中断时恢复它,以便在任务之间切换。过去的任务调度系统(TSS)是一种历史技术,而现代操作系统实现了用户模式调度器(UMS)机制来进行任务管理,与 TSS 相比非常复杂。

中断描述符表 (IDT)

中断描述符表(IDT)的实现也属于系统范围表的定义,负责存储中断和异常处理程序。它包含一些描述符,最终指向中断服务处理程序例程(ISR)的物理位置,这些例程旨在处理硬件中断、软件中断、异常和系统调用。IDT(中断描述符表)是操作系统(OS)和这些事件之间处理和调度中断和异常的基本组件,为更有效的操作提供了空间。

线程局部存储段 (TLS)

线程局部存储(TLS)段是一个独有的段,用于在多线程应用程序中存储线程特定的数据。进程中的每个线程都可以拥有一个完全属于自己的 TLS 段,用于保存线程局部变量和数据。TLS 段能够高效且线程安全地访问线程特定数据,无需互斥锁或信号量等同步技术。TLS 段在多线程应用程序必须针对性能和可伸缩性进行优化的条件下特别有用。

段描述符的实际实现

1. X86 架构

x86 架构中的段描述符是多样化安全机制和内存管理的关键要素。x86 架构支持两种主要的段描述符类型:GDT(全局描述符表)LDT(局部描述符表)

  • 全局描述符表 (GDT):GDT 是一个多用途表,包含系统中所有内存段的内存中的段描述符,可供 OS 和应用程序使用。GDT 地址由段选择器寄存器(SSR)使用,该寄存器专门用于将位置指针传递给所需段的系统。
  • 局部描述符表 (LDT):LDT 作为 GDT 的附加表,是一个面向进程的段描述符表,用于进程自身的特定需求。该进程可以拥有自己的 LDT,从而提供单独的字和访问控制的灵活性。LDT 通常被创建为说明面向进程的、自定义定义的特定步骤和权限。

在实际实现中,Linux 或 Windows 等操作系统使用描述符来进行内存分段保护、虚拟内存以及隔离计算机系统上进程的手段,这些系统具有 x86 架构。

ARM 架构

ARM 模型中,内存处理主要由内存保护单元(MPU)和内存管理单元(MMU)管理。然而,与 x86 处理器不同,ARM 处理器不包含额外的段描述符代码来简化任务。

  • 内存保护单元 (MPU):MPU 可以通过条件性地设置内存区域及其相应的属性(如基地址、大小、读、写和执行权限以及内存类型(强序、设备、正常))来以细粒度的方式配置内存保护。MPU 配置中的每个 MPU 内存空间(区域)都将充当段描述符,携带内存段的所有特征。
  • 内存管理单元 (MMU):MMU 是虚拟内存、地址转换和页面保护算法实现的一部分。这种类型的虚拟内存通常被称为分页,并使用页表来执行内存管理功能,这些功能实际上是虚拟地址及其对应物理地址的列表。虽然 MMU 的功能与段描述符不完全相同,但 MMU 的配置可以通过基于页面的内存访问和保护来完成相同的事情。

基于 ARM 的操作系统(如 Android 和 iOS)使用 MPU 和 MMU 配置来控制内存保护、虚拟内存和进程隔离。MPU 配置识别与特定访问权限级别相关的内存区域,而 MMU 配置提供虚拟到物理地址转换以及页面级安全,从而实现无干扰的软件运行。

虚拟化和段描述符

客户机和主机段描述符

  • 在虚拟化环境中,每个虚拟机都有自己的一组客户机段描述符,这些描述符对于每个客户机是独立的。这些客户机段描述符提供了虚拟机可用的内存段,并在虚拟机内强制执行内存保护策略。
  • 在主机系统上,Hypervisor 控制物理资源分配和硬件设备的访问。因此,Hypervisor 运行一组聚合的段描述符,称为主机段描述符。这些主机段描述符指定了虚拟机中堆叠的虚拟化硬件资源,并且模拟器控制计算机内存、CPU 寄存器和输入设备。

地址转换和重映射

  • 段描述符用于地址转换机制,以从客户机虚拟机的虚拟内存空间向主机系统中使用的物理内存空间提供物理地址映射。虚拟内存管理器(Hypervisor)负责转换内存地址。段描述符和页表通过拦截客户机虚拟机发出的内存访问请求的物理地址,并将其转换为虚拟地址来执行此过程。
  • 内存描述符在重映射段中发挥作用,当需要调整每个虚拟机的内存映射和分配资源时,Hypervisor 可以按需执行重映射。这种动态内存管理带来了高效的资源基础,甚至可以保护虚拟机免受彼此的内存访问。

内存保护和隔离

  • 段草案通过在段级别实施访问控制策略来保护内存,并在虚拟机之间实现隔离。每个虚拟机都有自己的段描述符,具有不同的访问权限和特权,以防止未经授权的访问和其他虚拟机的内存区域所有权。

操作系统在段描述符管理中的作用

  • 动态分配和去分配:同样,操作系统负责根据进程的内存需求分配和去分配段。然后,操作系统定义描述分配给进程的内存段的段描述符。同样,当进程终止或卸载时,操作系统会去分配相应的段描述符以释放内存资源。
  • 内存保护和访问控制:操作系统使用段描述符来实施内存保护和访问控制策略,以确保资源分配给每个需要它的人。通过生成具有控制访问权限(如读、写和特权级别)的各种描述符,内存管理得到了很好的执行,以调节进程如何与内存空间交互。通过对段描述符的有效控制,操作系统可以解决与违反文件权限、缓冲区溢出和其他安全问题相关的各种问题,这些问题可能会泄露一些重要信息。
  • 进程地址空间组织:上下文指示符有助于创建每个进程在段空间中的地址。操作系统将进程的地址空间划分为独立的区域,每个区域分配用于特定目的并具有相应的访问权限。例如,通用操作系统将代码、数据、堆栈和堆区域分开,这带来了高效的内存管理和保护。通过分块覆盖,进程描述符的管理有助于为进程分配地址空间,最大限度地减少不同字段之间的冲突,并优化内存利用率。
  • 上下文切换和内存管理:在进程进行上下文切换时,操作系统会保存并恢复段描述符的值,以确保内存隔离和保护。它在更新的内存描述符中更新段描述符,以反映当前调度的进程,并为每个进程分配其内存空间。此外,操作系统可能会通过引入内存段描述符来应用内存交换或分页技术,使进程在物理内存有限时能够将访问数据存储在辅助存储中。
  • 硬件抽象和优化:硬件的管理,特别是段描述符的语义,出现在工作系统提供的抽象细节中,作为与内存交互的统一接口呈现给应用程序。它通过利用 CPU 配置中的记录碎片支持等硬件特性,优化了段描述符的操作,以最小化开销并提高速度。通过智能地分配和管理段描述符,操作系统可以利用越来越多的硬件资源,从而提高整个系统的响应能力和可伸缩性。