[Linux]虚拟地址到物理地址的转化
@水墨不写bug


在这里插入图片描述


文章目录

  • 一、再次认识地址空间
  • 二、页表
    • 1、页表的结构设计
    • 2、页表节省了空间,省在哪里?
    • 3、页表的物理实现


一、再次认识地址空间

OS和磁盘交互的内存基本单位是4KB,这4KB通常被称为内存块OS对内存管理的粒度精确到块——4KB为单位。而与之相对的,用户对内存管理的粒度精确到1byte。在物理内存上,每一个块都有自己的地址——逻辑块地址Logical Block Address)。
这里的块,和文件数据存储的块的大小是相同的。OS管理的不是连续的物理内存,物理地址被划分为4KB为单位的块,OS通过管理这些块,间接管理内存。想要管理好这些块,需要先描述,再组织。在内核中,每一个块通过一个结构体来管理:

struct page {unsigned long flags;          // 页状态标志位(核心字段)union {struct {                  // 页缓存/匿名页的通用字段struct list_head lru; // LRU链表(用于页回收)void *mapping;        // 关联的地址空间(文件或匿名)pgoff_t index;        // 页在映射中的偏移或交换槽索引unsigned long private;// 私有数据(用途因场景而异)};struct {                  // Slab分配器专用字段union {struct list_head slab_list;struct {         // Partial页链表(用于slab)struct page *next;int pages;   // 当前slab的剩余页数int pobjects; // 剩余对象数};};struct kmem_cache *slab_cache; // 所属的slab缓存void *freelist;       // 空闲对象链表union {void *s_mem;      // slab第一个对象的地址unsigned long counters; // 引用计数和状态};};// 其他联合体分支(如设备页、大页等)};atomic_t _refcount;           // 引用计数atomic_t _mapcount;           // 页表映射计数unsigned long compound_head;  // 复合页(大页)的头页unsigned int compound_order;   // 复合页的阶数(2^order页)// ... 其他体系结构相关字段
};

一整个物理内存,有4GB,共1048576个4KB,通过结构体数组来管理:

struct page memory[1048576];//每一个page都有下标

struct page内部都有哪些字段?分别有什么作用?
(1)_refcount-引用计数,表面这个page被多少个进程共享。如果多个进程共享这个page,一旦出现修改数据,需要进行写时拷贝。
(2)unsigned long flags-标记,32位标识,表面这个页的属性:是否有效,是否是脏页,是否被占用,是否被锁定。
(3)lru-将页连接到最近最少使用(LRU) 链表,用于页回收(如kswapd)。LRU_ACTIVE:活跃页链表(近期被访问过)。LRU_INACTIVE:非活跃页链表(候选回收页)。


内存中的4KB被称为页框文件数据的4KB被称为页帧
在这里插入图片描述
在这里插入图片描述

同时4KB的大小也方便了内存和磁盘进行存取以块为单位的文件数据。内存和磁盘进行IO的基本单位理所当然就是4KB。
考虑下面的这几个例子:

  • (1)即使内存暂时只需要1byte数据,OS也会直接把这1byte所在的4KB直接加载到内存。
  • (2)父子进程对于只读数据,是共享的;对于任意一方修改了一个全局变量,会发生写时拷贝OS实际上不是仅仅拷贝了一个变量的大小,而是拷贝了这个变量所在的页框(4KB)。
  • (3)malloc进行申请空间的时候–malloc(10),底层不是只申请了10字节空间,而是4KB,多余的空间就交给了malloc函数进行维护。
  • (4)共享内存的大小最好就是4KB(4096bytes)的整数倍,如果申请4097bytes,则实际申请了8KB,但是我们用户能够使用的大小仅仅是4097bytes—这就造成了空间的浪费。(OS保守起见,多申请的空间不给我们使用
  • (5)page可作为文件的内核级缓冲区,是通过字典树来把page排序,使得存储在不同的page内的文件可以方便的恢复。

根据局部性原理这个时间点使用了这1byte,在后续时间点很有可能会使用这1byte附近的数据。 对一个全局变量修改了,很有可能以后要对附近的数据进行修改。所以拷贝4KB是合理的。申请内存一次性申请4KB也是用到了池化思想,提高了效率


二、页表

1、页表的结构设计

页表是一个把进程虚拟地址转化为物理地址的结构。在x86体系下,物理地址有4GB(2的32次方),如果按照通常的一对一的映射,一个4字节的虚拟地址映射一个4字节的物理地址,一共需要的内存比实际拥有的内存还要多,这十分不合理。所以页表的映射不是简单的一对一映射。

在x86体系结构下,一个虚拟地址有32位,这个虚拟地址被分为 10 + 10 + 12
在这里插入图片描述
前10位 用于在页目录内部索引,中间10位用于在页表中索引,后12位用于在一个页框内偏移:
在这里插入图片描述
这样,我任何一个虚拟地址,都可以通过页表的机制,找到对应的物理地址!
在这里插入图片描述

在C/C++中,为什么只要获取一个变量的首地址就能够成功访问这个变量?

因为这个变量还有对应的类型
访问一个变量,需要首先获取虚拟地址,通过上述的转换机制,把虚拟地址1字节转换到物理地址具体某字节的地址。此外,变量类型在语言层面就告诉了编译器,编译器会编译生成对应的汇编语句:

考虑下面这些语句:

int x = 1234;
int y = *(&x);  // 通过首字节地址读取值//对应的汇编语句可能就是
mov eax, [0x1000]  ; 从地址 0x1000 开始读取 4 字节到寄存器 eax
mov [0x2000], eax  ; 将 eax 的值存储到地址 0x2000

mov eax, [0x1000]:处理器根据地址 0x1000 开始读取 4 字节(因为 eax 是 4 字节寄存器)。汇编层面会根据指令和寄存器的大小,自动决定读取的数据宽度。


2、页表节省了空间,省在哪里?

如果没有页表,直接一个物理地址对应一个虚拟地址这样映射,页表需要占用的空间就是(以x86为例,一个地址占用的空间为4bytes)(4+4)*4GB = 32GB,需要存储页表的空间就已经超过的整机的物理空间大小,显然不合理。
页表实际的大小为 页目录(4KB) + 所有页表(4KB * 1024)
4KB+4MB=4100KB = 4.00390625MB
通过上面的计算,实际上就可以通过近乎4MB的空间大小来实现整个页表结构。于是就把原来的32GB压缩到了4MB。


3、页表的物理实现

实际上CPU内部内置了MMU。MMU(内存管理单元,Memory Management Unit) 是计算机硬件中的一个核心组件,通常集成在 CPU 中,主要负责管理内存访问和地址转换
上述的页表的转换流程就是MMU的工作流程。
CPU引入MMU后,读取指令、数据需要访问两次内存:首先通过PC指针读取下一条指针的虚拟地址,虚拟地址需要通过查询页表得到物理地址,然后访问该物理地址读取指令、数据。为了减少因为频繁查页表导致的CPU性能下降,MMU引入了TLB,TLB(Translation Lookaside Buffer)可翻译为“地址转换后援缓冲器”。TLB就是页表的Cache,其中存储了当前最可能(最近)被访问到的页表项,其内容是部分页表项的一个副本。只有在TLB无法完成地址翻译任务时,才会到内存中查询页表,这样就减少了页表查询导致的处理器性能下降。
在这里插入图片描述


对整体过程而言:在这里插入图片描述

虚拟到物理地址转换的详细流程:

CPU通过PC指针获取下条指令的虚拟地址,访问MMU查询TLB里面是否已经缓存了此次虚拟到物理的映射?如果是,则转换结束;如果否,则需要访问页表。通过CR3寄存器获取页表物理地址,通过分级映射查找获取物理地址,并同时把此次访问的虚拟到物理的映射缓存到TLB,方便后续的再次映射(如果是循环逻辑,则后续访问都不需要再次查页表,十分高效)。


完~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/83323.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/83323.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/83323.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes(K8s)核心架构解析与实用命令大全

在容器化技术席卷全球的今天,Kubernetes(简称K8s,以“8”代替“ubernete”八个字母)已成为云原生应用部署和管理的核心基础设施。作为Google基于内部Borg系统开源打造的容器编排引擎,K8s不仅解决了大规模容器管理的难题…

基于微信小程序的scratch学习系统

博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言&#xff0…

postgresql 流复制中指定同步的用户

postgresql 流复制中指定同步的用户 在创建postgresql流复制的过程中,可以指定用户名。 主库pg_hba.conf配置 vi $PGDATA/pg_hba.conf host replication repl 192.168.56.12/32 md5 host all all 0.0.0.0/0 md5主库创建同步的用户 # 主库创建 replicator 流复制…

基于springboot的运动员健康管理系统

博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言&#xff0…

工具识别系统Python+深度学习+人工智能+卷积神经网络算法+TensorFlow+图像识别

一、介绍 工具识别系统,使用Python作为主要编程语言,基于TensorFlow搭建卷积神经网络算法,通过收集了8种常见的日常工具图片(“汽油罐(Gasoline Can)”, “锤子(Hammer)”, “钳子&…

2024 CKA模拟系统制作 | Step-By-Step | 8、题目搭建-创建 Ingress

目录 ​​​​​​免费获取题库配套 CKA_v1.31_模拟系统 一、题目 二、核心考点 Ingress 资源定义 Ingress Controller 依赖 服务暴露验证 网络层次关系 三、搭建模拟环境 1.创建命名空间 2.安装ingress ingress-nginx-controller 3.创建hello.yaml并部署 四、总结 …

关于uv 工具的使用总结(uv,conda,pip什么关系)

最近要开发MCP 项目,uv工具使用是官方推荐的方式,逐要了解这个uv工具。整体理解如下: 一.uv工具的基本情况 UV 是一个由 Rust 编写的现代化 Python 包管理工具,旨在通过极速性能和一体化功能替代传统工具(如 pip、vi…

嵌入式学习笔记 - 新版Keil软件模拟时钟Xtal灰色不可更改的问题

在新版Keil软件中,模拟时钟无法修改XTAL频率,默认只能使用12MHz时钟。‌这是因为Keil MDK从5.36版本开始,参数配置界面不再支持修改系统XTAL频率,XTAL选项变为灰色,无法修改。这会导致在软件仿真时出现时间错误的问题&…

Spring AI Image Model、TTS,RAG

文章目录 Spring AI Alibaba聊天模型图像模型Image Model API接口及相关类实现生成图像 语音模型Text-to-Speech API概述实现文本转语音 实现RAG向量化RAGRAG工作流程概述实现基本 RAG 流程 Spring AI Alibaba Spring AI Alibaba实现了与阿里云通义模型的完整适配,…

Java进阶---JVM

JVM概述 JVM作用: 负责将字节码翻译为机器码,管理运行时内存 JVM整体组成部分: 类加载系统(ClasLoader):负责将硬盘上的字节码文件加载到内存中 运行时数据区(RuntimeData Area):负责存储运行时各种数据 执行引擎(Ex…

数据类型检测有哪些方式?

typeof 其中数组 对象 null都会判断为Object,其他正确 typeof 2 // number typeof true //bolean typeof str //string typeof [] //Object typeof function (){} // function typeof {} //object typeof undefined //undefined typeof null // nullinstanceof 判断…

NodeJS全栈开发面试题讲解——P6安全与鉴权

✅ 6.1 如何防止 SQL 注入 / XSS / CSRF? 面试官您好,Web 安全三大经典问题分别从不同层面入手: 🔸 SQL 注入(Server端) 原理:恶意用户将 SQL 注入查询语句拼接,导致数据泄露或破坏…

npm error Cannot find module ‘negotiator‘ 的处理

本想运行npm create vuelatest,但提示: npm error code MODULE_NOT_FOUND npm error Cannot find module negotiator npm error Require stack: npm error - C:\Users\Administrator\AppData\Roaming\nvm\v18.16.1\node_modules\npm\node_modules\tuf-j…

Python爬虫:AutoScraper 库详细使用大全(一个智能、自动、轻量级的网络爬虫)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、AutoScraper概述1.1 AutoScraper介绍1.2 安装1.3 注意事项二、基本使用方法2.1 创建 AutoScraper 实例2.2 训练模型2.3 保存和加载模型2.4 数据提取方法2.5 自定义规则三、高级功能3.1 多规则抓取3.2 分页抓取3.3 代…

【Netty系列】解决TCP粘包和拆包:LengthFieldBasedFrameDecoder

目录 如何使用? 1. 示例代码(基于Netty) 2. 关键参数解释 3. 协议格式示例 4. 常见配置场景 场景1:长度字段包含自身 场景2:长度字段在消息中间 5. 注意事项 举个例子 完整示例:客户端与服务端交互…

哈尔滨工业大学提出ADSUNet—红外暗弱小目标邻帧检测新框架

ADSUNet: Accumulation-Difference-Based Siamese U-Net for inter-frame Infrared Dim and Small Target Detection 作者单位:哈尔滨工业大学空间光学工程研究中心 引用: Liuwei Zhang, Yuyang Xi, Zhipeng Wang, Wang Zhang, Fanjiao Tan, Qingyu Hou, ADSUNet: A…

Linux开发追踪(IMX6ULL篇_第一部分)

前言 参数:cortex-A7 698Mhz flash 8GB RAM 512M DDR3 2个100M网口 单核 初期: 一、安装完虚拟机之后,第一步先设置文件之间可以相互拷贝复制,以及通过CRT连接到虚拟机等 折磨死人了啊啊啊啊啊啊 1、关于SSH怎么安装…

【萌笔趣棋】网页五子棋项目测试报告

目录 一.项目介绍 (一)项目简介 (二)功能介绍 (三)页面展示 1.注册页面 2.登录页面 3.游戏大厅页面 4.游戏房间页面(对战) 二.功能测试 (一)出现的…

知识图谱增强的大型语言模型编辑

https://arxiv.org/pdf/2402.13593 摘要 大型语言模型(LLM)是推进自然语言处理(NLP)任务的关键,但其效率受到不准确和过时知识的阻碍。模型编辑是解决这些挑战的一个有前途的解决方案。然而,现有的编辑方法…

数据库,Spring Boot,数据源

您是对的,我之前的回答解释了Spring Boot在操作MySQL时不一定需要显式配置指定的数据源类型,因为它有自动配置机制,但没有直接点明在自动配置情况下“数据源是什么”。 在Spring Boot自动配置机制下,这个“数据源”指的是一个连接…