<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(1)》(17)

本文主要是介绍<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(1)》(17),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Linux操作系统原理分析之linux存储管理(1)》(17)

  • 6 Linux 存储管理
    • 6.1 80x86 的分段机制
      • 6.1.1 80x86 的虚拟存储空间
      • 6.1.2 段描述符表
      • 6.1.3 逻辑地址向线形地址的转换

6 Linux 存储管理

6.1 80x86 的分段机制

Linux 最早在 intel80386 机器上开发,当前也主要运行在 intel 80386、80486 和 pentium 系列机器上。按照管理把该机器系列统称 80x86,也称 i386。

80x86 机器中用于控制和管理内存的硬件机制称为存储器管理单元 MMU(memory manage unit)。

在 MMU 控制下,80x86 具有两种存储管理模式

👉实地址模式:cpu 只能寻址 1MB 空间,MS-DOS 操作系统就工作在实地址模式下;
👉受保护的虚地址模式(保护模式):80x86 提供了虚拟存储的硬件机制,它是 OS
实现多任务存储管理以及提供存储保护的硬件基础。Linux 就是在该模式下实现其各种功能的。

6.1.1 80x86 的虚拟存储空间

1.物理地址和虚拟地址

物理地址:通常出现在地址总线上的地址称为物理地址。内存空间有物理地址确定,所以内存又称为物理地址空间。内存的最大容量由物理地址长度决定。80x86 机器的地址总线为 32 位,故有它确定的物理地址空间的范围可达 232B,即 4GB。

虚拟地址:用户作业的地址空间是由逻辑地址确定的,逻辑地址就是机器指令中使用的地址,故逻辑地址空间的最大容量由机器地址长度决定。80x86 指令地址字长度 48 位,其中 46 位用于寻址,因此80x86 的逻辑地址地址空间最大可达 64T。故 80x86 提供给程序人员使用的逻辑地址空间远远大于实际的物理地址空间,是一个虚拟的存储空间。所以逻辑地址就是虚拟地址。

为了支持多道进行并发执行以及实现存储保护,80x86 存储管理机制把 64T 的逻辑地址空间分成性质
不同的两部分:

👉全局地址空间:所有进程共享的空间,通常存放 os 的程序和数据。
👉局部地址空间:由系统分配给各个进程使用,用于存放进程各自的程序和数据。

2. 地址转换方式
80x86 在保护模式下提供了两种地址转换方式:

👉分段机制
👉分段+分页的两级地址转换方式。(本书只介绍这种转换方式)。

  1. 分段分页地址转换
    在系统运行时,逻辑地址必须转换成物理地址才能访问物理内存。80x86 中分段分页的地址转换机制中需要两级地址转换:

👉第一级:由分段机制完成逻辑地址向线性地址的转换 由分段机制完成逻辑地址向线性地址的转换。分段机制把逻辑地址空间分成若干个相互独立的地址空间,它称为线性地址空间。线性地址空间的地址称为线性地址。每个线性地址空间从 0 开始编址,80x86 中线性地址是 32 位的,因此每个线性地址空间最大 4G。在多道系统中,每个线性地址可以供一个用户进程使用,这就保证了每个进程都有自己独立的虚拟存储空间 这就保证了每个进程都有自己独立的虚拟存储空间。

地址类型说明
逻辑地址面向用户,是用户在程序设计时使用的地址空间,也就是用户程序中指令访问的地址空间;
线性地址面向进程,使进程使用的地址空间,对用户透明

👉第二级:由分页机制完成线性地址向物理地址的转换

说明:
1)在 80x86 中,虚拟地址空间的全局和局部地址空间都被划分成不同段。64T 的虚拟地址空间最多可以分 16K 个段。每个段的最大长度可达 4G;
在这里插入图片描述

2)全局地址空间和局部地址空间各自最多可以有 8K 段,分别称为全局段和局部段。
3)由于虚拟存储空间不是实际存在的,所以其中的段的数量,段的大小是不确定的,是根据需要随时建立的。当然不能超过上面提到的最大限制。

6.1.2 段描述符表

80x86 的段描述符表就是前面原理部分提到的段表。段描述符就是段表表项,每个段描述符的长度为8B。80x86 提供两种不同的段描述符:

👉全局描述符表 GDT(Global Descriptor Table):描述全局段,故系统中只有一个全局描述符表
👉局部描述符表 LDT(Local Descriptor Table):描述各个进程的各个局部段。故系统中有多少进程就有多少 LDT。

1.全局描述符表 GDT
1)80x86 中,全局描述符表 GDT 中一般包括 3 种不同种类的描述符:

👉系统内核代码段和数据段的描述符
👉进程状态段 TSS(Task State Segment)的描述符。系统中每个进程都有一个 TSS 段,用于保存该进程的上下文。所有进程的 TSS 段描述符都集中的保存在 GDT 中。
👉LDT 描述符:对各个进程的局部描述符表 LDT 进行描述的描述符,记录各个进程的局部描述符 LDT 在线性地址空间的位置和长度。每个进程 LDT 描述符在 GDT 中的位置,由系统记录在该进程 TSS 段的一个 16 位的位域中,该位域的值称为 LDT 选择符。

2)全局描述符表寄存器(GDTR):记录 GDT 在线性地址空间中的位置
在这里插入图片描述

其中:

表基址:指出 GDT 的起始地址;
表限:表限的值加 1 位 GDT 的长度。

说明:16 位的表限确定了 GDT 的最大地址空间为 64K,由于每个描述符长度为 8B,因此 GDT 最多可以拥有 8K 个描述符。每个描述符对应一个段,因此系统中最多可以有 8K 个全局段。

2.局部描述符表 LDT:描述进程各个局部段的。
3.定位 LDT
因为单处理机中某个时刻只能有一个进程处于运行状态,所以在某个时刻只有当前进程的 LDT 处于活动(使用)状态。系统需要能迅速定位活动的 LDT。

80x86 通过局部描述表寄存器 LDTR 和相应的 LDT 高速缓存来实现定位 LDT。

👉局部描述表寄存器 LDTR: 是一个 16 位寄存器,它的作用是指出当前进程的 LDT 描述符在GDT 中的位置,也就是前面提到的 LDT 选择符。在进程切换时,从进程的 TSS 中取出 LDT 选择 符,并将它放入 LDTR 中; 在地址映射时,首先从 LDTR 中得到 LDT 选择符;然后 GDT 中根据 LDT 选择符找到 LDT描述符(即得到 LDT 的位置等信息),接下来才能找到 LDT(即段表)。显然这样是会严重影响程序运行速度的。故引入了 LDT 高速缓存。
👉LDT 高速缓存: 保存从 GDT 中找到的 LDT 描述符。引入 LDT 高速缓存后,第一次仍需要完成上面提到的三个步骤,但是第一次完成时,将从GDT 中找到的该进程的 LDT 描述符保存在了 LDT 高速缓存中。这样以后地址映射时,可以直接从高速缓存中得到 LDT 的位置等信息。

LDT 高速缓存:
在这里插入图片描述
说明:

16 位的表限确定了 LDT 的最大地址空间为 64K,由于每个描述符长度为 8B,因此LDT 最多可以拥有 8K 个描述符。每个描述符对应一个段,因此系统中最多可以有 8K 个局部段。

6.1.3 逻辑地址向线形地址的转换

1.基本过程(参照原理部分)
在 80x86 中逻辑地址的格式如下所示:
在这里插入图片描述
在 80x86 中,程序执行中读取每一条指令时都需要访问代码段。这时系统把逻辑地址中的选段符装入寄存器 CS 中,把段内偏址装入指令计数器 EIP 中,然后经过硬件分段机制把逻辑地址转成指向代码段的32 位线性地址。

程序中执行读写数据的指令时,系统把指令中逻辑地址的选段符装入 DS 寄存器中,把段内偏址装入某个通用寄存器中,然后经过硬件分段机制把逻辑地址转成指向数据段的 32 位线性地址。

2.段描述符寄存器(参照原理部分,快表)
选段寄存器:上述中设计到的寄存器,因为包含了选择某个段的索引值,故又称其为选段寄存器。

80x86 中有 6 个段寄存器:CS、DS、SS、ES、FS 和 GS;

段描述符寄存器:根据程序的局部性原理,为了提高地址映射速度,减少访问内存的次数。80x86 分段机制在高速缓存中,为每个选段寄存器都配置了一个对应的段描述符寄存器,用于保存当前访问的那些段的段描述符。

这篇关于<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(1)》(17)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/446015

相关文章

基于Linux的ffmpeg python的关键帧抽取

《基于Linux的ffmpegpython的关键帧抽取》本文主要介绍了基于Linux的ffmpegpython的关键帧抽取,实现以按帧或时间间隔抽取关键帧,文中通过示例代码介绍的非常详细,对大家的学... 目录1.FFmpeg的环境配置1) 创建一个虚拟环境envjavascript2) ffmpeg-py

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

详解Linux中常见环境变量的特点与设置

《详解Linux中常见环境变量的特点与设置》环境变量是操作系统和用户设置的一些动态键值对,为运行的程序提供配置信息,理解环境变量对于系统管理、软件开发都很重要,下面小编就为大家详细介绍一下吧... 目录前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流