[Linux]虚拟地址到物理地址的转化

news2025/6/2 23:36:09

[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.coloradmin.cn/o/2392387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux线程入门

目录 Linux线程概念 什么是线程 重新理解进程 线程的优点 线程的缺点 线程的异常 线程用途 Linux线程概念 什么是线程 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。一切进程至…

Kubernetes超详细教程,一篇文章帮助你从零开始学习k8s,从入门到实战

k8s 概述 k8s github地址:https://github.com/kubernetes/kubernetes 官方文档:https://kubernetes.io/zh-cn/docs/home/ k8s,全程是 kubernetes,这个名字源于希腊语,意为"舵手"或"飞行员” k8s 这…

OpenHarmony平台驱动使用(二),CLOCK

OpenHarmony平台驱动使用(二) CLOCK 概述 功能简介 CLOCK,时钟是系统各个部件运行的基础,以CPU时钟举例,CPU 时钟是指 CPU 内部的时钟发生器,它以频率的形式工作,用来同步和控制 CPU 内部的各…

我们是如何为 ES|QL 重建自动补全功能的

作者:来自 Elastic Drew Tate Elasticsearch 拥有许多新功能,可以帮助你根据使用场景构建最佳搜索方案。浏览我们的示例笔记本了解更多内容,开始免费试用云服务,或者立即在本地机器上尝试 Elastic。 对于我们开发者来说&#xff0…

MATLAB在逐渐被Python淘汰吗

MATLAB在学术研究、工程仿真、数值计算等传统领域仍占据一席之地,但Python因其开源免费、生态丰富、易于集成的优势,正在快速崛起,逐步蚕食MATLAB的市场份额。尤其在人工智能、数据分析和科学计算等领域,Python的优势愈发明显。例…

Git 使用规范

Git 使用规范 一、版本控制的核心原则 🧭二、分支策略(Branch Strategy) 🌿2.1 分支类型与命名规范2.2 可视化流程图 三、提交信息规范(Commit Message)✍️3.1 提交格式3.2 Type 类型说明 四、Tag 版本规范…

代码随想录第43天:图论4(最小生成树、拓扑排序)

一、冗余的边II(Kamacoder 109) from collections import defaultdict# 并查集 - 查找根节点(路径压缩) def find(fa, x):if fa[x] ! x:fa[x] find(fa, fa[x])return fa[x]# 并查集 - 合并两个集合,返回是否合并成功 …

AI智能体|扣子(Coze)搭建【自动生成超高质量PPT】工作流

各位好久不见,你的失踪人口又回来了,已经超过一周的时间没有进行文章的更新了。 没更新的这段时间,主要还是因为工作上的调整以及身体生病所导致的停更,具体以后再说。 我们先讲今天的主要主题,使用 Coze 智能体一键生…

文档处理的相关工具

目前网页端的文档,可以通过沉浸式翻译来进行翻译阅读和学习。 但是某些文献只有pdf下载的版本,所以需要一个免费的针对pdf的翻译工具。 保留公式和图片格式。 推荐一个pdf翻译的工具,可以自己部署使用。如果需要word版本,后面讨论…

java基础(面向对象进阶高级)内部类

内部类 内部类概述、成员内部类 (了解) 内部类创建对象: 一定要继承外部类对象,才能创建内部类对象。 拓展:成员内部类访问外部类的成员特点: 成员内部类中,是否可以直接访问外部类的实例成员?? 当然可以啊&#x…

使用Python,OpenCV,Tesseract-OCR对自己的运动数据图片进行识别及分析,并使用Matplotlib绘制配速图出来

使用Python,OpenCV,Tesseract-OCR对自己的运动数据图片进行识别及分析,并使用Matplotlib绘制配速图出来 1. 效果图2. 源码3. 全量源码及运动图片资源参考主要分为 目录下图片解析及读取;拼九宫格图片出来,可以自由配置(m*n)取决于自己有多少张运动图片遍历图片并进行运动…

小白的进阶之路系列之七----人工智能从初步到精通pytorch自动微分优化以及载入和保存模型

本文将介绍Pytorch的以下内容 自动微分函数 优化 模型保存和载入 好了,我们首先介绍一下关于微分的内容。 在训练神经网络时,最常用的算法是反向传播算法。在该算法中,根据损失函数相对于给定参数的梯度来调整参数(模型权重)。 为了计算这些梯度,PyTorch有一个内置…

创建型模式之 Builder (生成器)

创建型模式之 Builder (生成器) 摘要: 本文介绍了生成器(Builder)设计模式,属于创建型模式之一。该模式通过将复杂对象的构建与表示分离,使同一构建过程能创建不同表现形式。文章以小米汽车不同配置版本为例说明了模式…

智能物资出入库管控系统

概述 智能物资管理系统利用RFID自动识别技术,物联网技术、人脸识别、指纹、指静脉生物识别技术,应用于军械装备的管理,可实时准确采集军械装备编配、 储存、供应、使用等数据,实时掌握军械装备物资的分布及数量 状况。细化管理到…

机器学习-线性回归基础

一、什么是回归 依据输入x写出一个目标值y的计算方程,求回归系数的过程就叫回归。简言之:根据题意列出方程,求出系数的过程就叫做回归。 回归的目的是预测数值型的目标值y,分类的目的预测标称型的目标值y。 二、线性回归 2.1线性…

[Vue组件]半环进度显示器

[Vue组件]半环进度显示器 纯svg实现&#xff0c;不需要其他第三方库&#xff0c;功能简单&#xff0c;理论上现代浏览器都能支持 封装组件 所有参数都选填&#xff0c;进度都可选填 <template><div class"ys-semiring"><div class"svg-container…

科技赋能建筑行业,智能楼宇自控系统崭露头角成发展新势力

在科技浪潮席卷全球的时代背景下&#xff0c;传统建筑行业正面临着前所未有的变革压力。随着城市化进程加快&#xff0c;建筑规模与复杂度不断攀升&#xff0c;能源消耗、运营效率、用户体验等问题日益凸显。智能楼宇自控系统凭借物联网、大数据、人工智能等前沿技术&#xff0…

白杨SEO:做AI搜索优化的DeepSeek、豆包、Kimi、百度文心一言、腾讯元宝、通义、智谱、天工等AI生成内容信息采集主要来自哪?占比是多少?

大家好&#xff0c;我是白杨SEO&#xff0c;专注SEO十年以上&#xff0c;全网SEO流量实战派&#xff0c;AI搜索优化研究者。 在开始写之前&#xff0c;先说个抱歉。 上周在上海客户以及线下聚会AI搜索优化分享说各大AI模型的联网搜索是关闭的&#xff0c;最开始上来确实是的。…

显示docker桌面,vnc远程连接docker

目录 相关概念&#xff1a; 实现步骤&#xff1a; 1.启动docker容器 2.安装x11 3.Docker 容器中安装一个完整的图形桌面&#xff08;XFCE&#xff09;和 VNC 远程桌面服务器&#xff08;TightVNC&#xff09; 4.配置vncservice 5.本地安装VNC Viewer连接VNC Viewer下载地…

腾讯云国际站性能调优

全球化业务扩张中&#xff0c;云端性能直接决定用户体验与商业成败。腾讯云国际站通过资源适配、网络优化与存储革新&#xff0c;为企业提供全链路调优方案。 ​​资源精准适配​​ 实例选型需与业务场景深度耦合&#xff0c;计算优化型实例加速AI训练效率3倍&#xff0c;内存…