Linux下逻辑地址、线性地址、物理地址详细总结

Linux-0.11内核源码分析系列:关于线性地址,逻辑地址,物理地址的关系与区别 /* *Author : DavidLin *Date : 2014-11-22pm *Email : linpeng1577@163.com or linpeng1577@gmail.com *world : the city of SZ, in China *Ver : 000.000.001 *h 阅读详情


一、逻辑地址转线性地址
    
机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。

我们写个最简单的hello world程序,用gcc编译,再反编译后会看到以下指令:
  1. mov    0x80495b0, %eax
复制代码

这里的内存地址0x80495b0 就是一个逻辑地址,必须加上隐含的DS 数据段的基地址,才能构成线性地址。也就是说 0x80495b0 是当前任务的DS数据段内的偏移。

 

在x86保护模式下,段的信息(段基线性地址、长度、权限等)即段描述符占8个字节,段信息无法直接存放在段寄存器中(段寄存器只有2字节)。Intel的设计是段描述符集中存放在GDT或LDT中,而段寄存器存放的是段描述符在GDT或LDT内的索引值(index)。

Linux中逻辑地址等于线性地址。为什么这么说呢?因为Linux所有的段(用户代码段、用户数据段、内核代码段、内核数据段)的线性地址都是从 0x00000000 开始,长度4G,这样 线性地址=逻辑地址+ 0x00000000,也就是说逻辑地址等于线性地址了。

这样的情况下Linux只用到了GDT,不论是用户任务还是内核任务,都没有用到LDT。GDT的第12和13项段描述符是 __KERNEL_CS 和__KERNEL_DS,第14和15项段描述符是 __USER_CS 和__USER_DS。内核任务使用__KERNEL_CS 和__KERNEL_DS,所有的用户任务共用__USER_CS 和__USER_DS,也就是说不需要给每个任务再单独分配段描述符。内核段描述符和用户段描述符虽然起始线性地址和长度都一样,但DPL(描述符特权级)是不一样的。__KERNEL_CS 和__KERNEL_DS 的DPL值为0(最高特权),__USER_CS 和__USER_DS的DPL值为3。
用gdb调试程序的时候,用info reg 显示当前寄存器的值:
  1. cs             0x73     115
  2. ss             0x7b     123
  3. ds             0x7b     123
  4. es             0x7b     123
复制代码

可以看到ds值为0x7b, 转换成二进制为 00000000 01111011,TI字段值为0,表示使用GDT,GDT索引值为 01111,即十进制15,对应的就是GDT内的__USER_DATA 用户数据段描述符。
从上面可以看到,Linux在x86的分段机制上运行,却通过一个巧妙的方式绕开了分段。Linux主要以分页的方式实现内存管理。

二、线性地址转物理地址

前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。

分页是CPU提供的一种机制,Linux只是根据这种机制的规则,利用它实现了内存管理。

分页的基本原理是把线性地址分成固定长度的单元,称为页(page)。页内部连续的线性地址映射到连续的物理地址中。X86每页为4KB(为简化分析,我们不考虑扩展分页的情况)。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table),页表存放在内存中。

在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。如果PG=0,则分页机制无效,线性地址就直接作为物理地址。

为了实现每个任务的平坦的虚拟内存和相互隔离,每个任务都有自己的页目录表和页表。

为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。

32位的线性地址被分成3个部分:

最高10位 Directory 页目录表偏移量,中间10位 Table是页表偏移量,最低12位Offset是物理页内的字节偏移量。

页目录表的大小为4KB(刚好是一个页的大小),包含1024项,每个项4字节(32位),表项里存储的内容就是页表的物理地址(因为物理页地址4k字节对齐,物理地址低12位总是0,所以表项里的最低12字节记录了一些其他信息,这里做简化分析)。如果页目录表中的页表尚未分配,则物理地址填0。

页表的大小也是4k,同样包含1024项,每个项4字节,内容为最终物理页的物理内存起始地址。

 

每个活动的任务,必须要先分配给它一个页目录表,并把页目录表的物理地址存入cr3寄存器。页表可以提前分配好,也可以在用到的时候再分配。

还是以 mov    0x80495b0, %eax  中的地址为例分析一下线性地址转物理地址的过程。

前面说到Linux中逻辑地址等于线性地址,那么我们要转换的线性地址就是0x80495b0。转换的过程是由CPU自动完成的,Linux所要做的就是准备好转换所需的页目录表和页表(假设已经准备好,给页目录表和页表分配物理内存的过程很复杂,后文再分析)。

内核先将当前任务的页目录表的物理地址填入cr3寄存器。

线性地址 0x80495b0 转换成二进制后是 0000 1000 0000 0100 1001 0101 1011 0000,最高10位0000 1000 00的十进制是32,CPU查看页目录表第32项,里面存放的是页表的物理地址。线性地址中间10位00 0100 1001 的十进制是73,页表的第73项存储的是最终物理页的物理起始地址。物理页基地址加上线性地址中最低12位的偏移量,CPU就找到了线性地址最终对应的物理内存单元。

我们知道Linux中用户进程线性地址能寻址的范围是0 - 3G,那么是不是需要提前先把这3G虚拟内存的页表都建立好呢?一般情况下,物理内存是远远小于3G的,加上同时有很多进程都在运行,根本无法给每个进程提前建立3G的线性地址页表。Linux利用CPU的一个机制解决了这个问题。进程创建后我们可以给页目录表的表项值都填0,CPU在查找页表时,如果表项的内容为0,则会引发一个缺页异常,进程暂停执行,Linux内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。

怎样防止进程访问不属于自己的线性地址(如内核空间)或无效的地址呢?内核里记录着每个进程能访问的线性地址范围(进程的vm_area_struct 线性区链表和红黑树里存放着),在引发缺页异常的时候,如果内核检查到引发缺页的线性地址不在进程的线性地址范围内,就发出SIGSEGV信号,进程结束,我们将看到程序员最讨厌看到的Segmentation fault。


转自:http://bbs.chinaunix.net/thread-2015439-1-1.html

linux内存管理---物理地址、线性地址、虚拟地址、逻辑地址之间的转换 这几个地址之间的转换 阅读详情

相关推荐

Anomalib实战:从零开始构建自定义数据集的异常检测模型

本文详细介绍了如何使用Anomalib 2.1.0从零开始构建自定义数据集的异常检测模型。通过实战演示,指导读者准备符合规范的数据集结构,快速上手训练Patchcore等先进算法,并完成模型推理与调优,为工业质检、医疗影像等场景提供高效的视觉异常检测解决方案。

weixin_29165465的博客 109

Linux命令之fdisk --磁盘分区工具

磁盘分区工具的讲解和使用

m0_71163619的博客 1万+

从零到一:AVL Cruise与Matlab联合仿真DLL配置的避坑指南

本文详细介绍了AVL Cruise与Matlab联合仿真DLL配置的全流程,包括编译器选择、环境变量设置、DLL编译与模型导出等关键步骤。针对常见问题如版本匹配、路径错误等提供了实用解决方案,帮助工程师高效实现控制策略与整车性能仿真的无缝对接。

weixin_29054399的博客 567

Linux内存管理图解

转自: http://www.cublog.cn/u3/94690/showart_2051283.htmlLinux内存管理图解作者:wdy一、逻辑地址转线性地址   机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。我们写个最简单的hello world程序,用gccs编译,再反编译后会看到以下指令:mov    0x80495b0, %eax这里的内存地址0x80495b0 就是一个逻辑地址,必须加上隐含的DS 数据段的

guogaofeng1219的专栏 1131

相机标定原理与张氏标定法

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

heeweii的博客 2280

【第三方互联】3、腾讯QQ授权第三方登录

当我们创建的 QQ 互联应用成功后,我们便可以开始使用该应用来实现 QQ 互联 一、获取 APP ID 和 APP Key 1、找到我的应用 2、点击应用,进入详情 这样,我们就获取到了 APP ID 和 APP Key 二、进行开发 1、将 APP ID 、APP Key,以及该应用的信息放入项目中的配置文件中,我使用的是SpringBoot,我放在了 application.y...

JACKAL 22万+

linux分配磁盘空间命令

创建新的分区->更新内核分区表->初始化新分区作为物理卷->将新物理卷添加到现有卷组->扩展需要扩容的逻辑卷->调整文件爱你系统大小以匹配新的逻辑卷大小。如图,600G,但实际分配了一共1+99G,剩余500G,我们需要通过命令进行剩余存储的分配。假设我需要将剩余500G,分配给我的根目录,对应卷名为oepneuler-root。5、 扩展逻辑卷 openeuler-root (根目录)使用卷组中的所有可用空间。4、 将新物理卷添加到现有的卷组 (可通过pvdisplay命令查询卷名称)

qq_44820964的博客 1088

15、基于最优传输的协作多视图聚类框架

本文提出了一种基于最优传输理论的协作多视图聚类框架,通过引入协作学习机制在不同视图间建立先验交互,以提升共识聚类的质量。框架包含两种新方法:协作共识投影方法(CoCP)和基于新表示的协作共识方法(CoCNR)。CoCP在全局空间中整合多视图信息并进行共识投影,而CoCNR则通过协作编码生成新的数据表示以实现更优聚类。方法利用熵正则化的Wasserstein距离与Wasserstein重心,有效捕捉数据分布间的几何结构,并通过聚合步骤获得统一模型。实验结果表明,所提方法在多个数据集上均优于现有方法,具有良好的

gpt4scribbler的博客 85

磁盘管理,分区的两种格式,查看分区信息;fdisk(MBR)和gdisk(GPT)去管理分区,格式化(形成文件系统),挂载(临时挂载和永久挂载)

Command(mforhelp)w#保存并退出。forhelp)n#创建一个新的分区。Select(defaultp)#默认创建一个主分区。Command(mforhelp)n#创建一个分区。先去添加一块SATA硬盘,然后开机查看是否加载到新的硬盘,如果检测到再进行管理操作。...

weixin_67259816的博客 1676

【论文复现】水下单光子激光雷达设计 Sequential Multimodal Underwater Single

针对对慢速小水下目标进行远距离、高分辨率重建的需求,单光子激光雷达(LiDAR)目标重建技术的研究正在进行。本文报告了一种基于时空序列融合的顺序多模态水下单光子 LiDAR 自适应目标重建算法,该算法具有强大的信息提取和噪声过滤能力,能够从复杂的回波光子计数和空间像素关系中重建目标的深度和反射强度信息。该方法包括三个步骤:数据预处理、序列优化极值推断滤波以及图像优化协同变分策略,以实现复杂水下环境下的高质量目标重建。

u012133341的博客 293

【YOLO11改进 - C3k2融合】C3k2融合AKConv(可改变核卷积)二次创新:任意数量的参数和任意采样形状的即插即用的卷积

【YOLO11改进 - C3k2融合】C3k2融合AKConv(可改变核卷积)二次创新:任意数量的参数和任意采样形状的即插即用的卷积

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 407

深入理解Linux内存分配

为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化。除此之外,你有可能会选择在函数内部去声明局部变量,又或者为变量动态申请内存。 不管你在用户程序中采取哪种方式申请内存,这些都对应着不同的内存分配方式以及不同的数据段,如果再加上代码段,就构成了一个完整的进程。由此可见,一个完整的进程在内存空间中对应着不同的数据区,具体来说,对应着五种不同的数据区: 代码段,存放操作指令;数据段,存放已初始

木牛的博客 1512

突破限制:巧用Azure OpenAI,畅玩Gemini模型

通过 Azure OpenAI 服务这一巧妙的途径,间接调用 Gemini 模型,打破网络限制的壁垒。本文将详细介绍这一方法,无论你是人工智能领域的新手,还是经验丰富的开发者,都能从中获取实用的技巧,轻松开启 Gemini 模型的探索之旅

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 181

LINUX 逻辑地址、线性地址、虚拟地址和物理地址

1、概念解释 物理地址: 用于内存芯片级的单元寻址,与地址总线相对应。这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对...

十一月zz的博客 7817

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Linux之逻辑地址、线性地址、物理地址

程序代码(逻辑地址) → MMU段转换(物业登记) → 线性地址(内部单号)↓ ↓ ↓├─ 段式管理(地址空间隔离) ──┼── 页式管理(内存分配优化)──┤↓ ↓ ↓物理内存(真实货架) ← MMU页转换(仓库查找) ← 线性地址(内部单号)地址类型作用描述类比场景逻辑地址程序使用的「抽象地址」,隔离进程空间,提供权限控制用户填写的快递地址线性地址操作系统管理的「虚拟连续空间」,通过页表映射到物理内存快递分拣中心的内部单号物理地址。

Mr_-G,一名勤奋底层软件开发工程师的博客 1221

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

linux内存管理---虚拟地址、逻辑地址、线性地址、物理地址的区别(一)

虚拟地址 、物理地址 、线性地址 、逻辑地址

鱼思故渊的专栏 2万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Linux下逻辑地址-线性地址-物理地址图解

机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。

wxzking的专栏 1万+

linux内核中 逻辑地址、虚拟地址、线性地址和物理地址大扫盲

很多讲linux内核的书里面都提到过这四个概念:逻辑地址、虚拟地址、线性地址和物理地址。物理地址比较好澄清,但是这些书里都没有明确的讲清楚所谓的逻辑地址、虚拟地址、线性地址的区别到底是什么? 那本文就来个大扫除吧。 中英文对应关系: 逻辑地址 --- logical address; 虚拟地址 --- virtual address; 线性地址 --- linear address; 物理地址 --- physical address; 这四个地址是体系相关的,我以x86 cpu为例进行解释。

ludongguoa的博客 2639

Linux内存管理:逻辑地址到线性地址和物理地址的转换

本文图文结合简单清晰的讲述了Linux内核中逻辑地址到线性地址和线性地址到物理地址的转换过程

焦坪煤矿的wdy 3310

Linux下逻辑地址、线性地址、物理地址(系列一:概要)

转载:Linux下逻辑地址、线性地址、物理地址详细总结 转载原因:通俗易懂,逻辑清晰。 一、逻辑地址转线性地址 机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。 我们写个最简单的hello world程序,用gcc编译,再反编译后会看到以下指令: ...

Yannick Jiang 的专栏 289

linux下逻辑地址-线性地址-物理地址图解

一、逻辑地址转线性地址     机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。 我们写个最简单的hello world程序,用gccs编译,再反编译后会看到以下指令: mov    0x80495b0, %eax 这里的内存地址0x80495b0 就是一个逻辑地址,必须加上隐含的DS 数据段的基地址,才能

L_Nan的专栏 3566

linux内核—逻辑地址/线性地址/物理地址 转换

概念 1.逻辑地址 包含在机器语言指令中用来指定一个操作数或一条指令的地址。每个逻辑地址都由一个段和偏移量组成,偏移量指明了从段开始的地方到实际地址之间的距离 2.线性地址 即虚拟地址,是一个32位无符号整数,用来表示4G的地址 3.物理地址 实际内存芯片上的地址 在linux中,由于所有的段都是从0x00000000开始,所以逻辑地址和线性地址是相同的,也就是在linux中忽略逻辑地址这个概念即可 线性地址转换物理地址 linux使用三级页表转换,与二级页表转换原理相似,以下按二级页表说明 32位线性地址

chengcheng1024的博客 814

Linux中的逻辑地址,线性地址和物理地址转换关系

转载自:http://blog.youkuaiyun.com/erazy0/article/details/6457626 一、逻辑地址转线性地址     机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。 我们写个最简单的hello world程序,用gcc编译,再反汇编后会看到以下指令: mov    0

starl1985的专栏 1182

物理地址_linux内核中 逻辑地址、虚拟地址、线性地址和物理地址大扫盲

关注”技术简说“(b站同名),带你由浅入深学习linux内核源码。linux内核开发100讲免费教程,每天晚上9点准时更新,敬请收看。进我主页点”视频“栏目即可观看。很多讲linux内核的书里面都提到过这四个概念:逻辑地址、虚拟地址、线性地址和物理地址。物理地址比较好澄清,但是这些书里都没有明确的讲清楚所谓的逻辑地址、虚拟地址、线性地址的区别到底是什么?那本文就来个大扫除吧。中英文对应关系:逻辑地...

weixin_31156651的博客 424
上一篇: 【汇编】计算机寄存器介绍
下一篇: 操作系统内存管理概述
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值