Linux下逻辑地址-线性地址-物理地址图解(转)
一、逻辑地址转线性地址
机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。
我们写个最简单的hello world程序,用gccs编译,再反编译后会看到以下指令:
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 显示当前寄存器的值:
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
可以看到ds值为0x7b, 转换成二进制为 00000000 01111011,TI字段值为0,表示使用GDT,GDT索引值为 01111,即十进制15,对应的就是GDT内的__USER_DATA 用户数据段描述符。
从上面可以看到,Linux在x86的分段机制上运行,却通过一个巧妙的方式绕开了分段。
Linux主要以分页的方式实现内存管理。
二、线性地址转物理地址
前面说了Linux中逻辑地址等于线性地址,那么线性地址怎么对应到物理地址呢?这个大家都知道,那就是通过分页机制,具体的说,就是通过页表查找来对应物理地址。
准确的说分页是CPU提供的一种机制,Linux只是根据这种机制的规则,利用它实现了内存管理。
在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。如果PG=0,则分页机制无效,线性地址就直接做为物理地址。
分页的基本原理是把内存划分成大小固定的若干单元,每个单元称为一页(page),每页包含4k字节的地址空间(为简化分析,我们不考虑扩展分页的情况)。这样每一页的起始地址都是4k字节对齐的。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table)。注意,为了实现每个任务的平坦的虚拟内存,每个任务都有自己的页目录表和页表。
为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。
32位的线性地址被分成3个部分:
最高10位 Directory 页目录表偏移量,中间10位 Table是页表偏移量,最低12位Offset是物理页内的字节偏移量。
页目录表的大小为4k(刚好是一个页的大小),包含1024项,每个项4字节(32位),项目里存储的内容就是页表的物理地址。如果页目录表中的页表尚未分配,则物理地址填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内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。
Linux下逻辑地址-线性地址-物理地址图解(转)的更多相关文章
- Linux下逻辑地址、线性地址、物理地址详细总结
Linux下逻辑地址.线性地址.物理地址详细总结 一.逻辑地址转线性地址 机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址 ...
- [转帖]Linux下逻辑地址、线性地址、物理地址详细总结
Linux下逻辑地址.线性地址.物理地址详细总结 https://www.cnblogs.com/alantu2018/p/9002441.html 总结的挺好的 现在应该是段页式管理 使用MMU和T ...
- CentOS/Linux下设置IP地址
CentOS/Linux下设置IP地址 1:临时修改:1.1:修改IP地址# ifconfig eth0 192.168.100.100 1.2:修改网关地址# route add default g ...
- 嵌入式 Linux下修改MAC地址
Linux下修改MAC地址 方法一: 1.关闭网卡设备ifconfig eth0 down2.修改MAC地址ifconfig eth0 hw ether MAC地址3.重启网卡ifconfig eth ...
- 获取Linux下的IP地址 java代码
/** * 获取Linux下的IP地址 * * @return IP地址 * @throws SocketException */ public static String getLinuxLocal ...
- linux下修改IP地址的方法
linux下修改IP地址的方法 1.网卡的命名规则 在centos7中,en表示着:ethernet以太网,即现在所用的局域网,enX(X常见有以下3种类型) 2.IP地址的临时修改(重启后失效) 查 ...
- Linux下配置ip地址四种方法
linux系统安装完,以后通过命令模式配置网卡IP.配置文件通常是/etc/sysconfig/network-scripts/ifcfg-interface-nameifconfig后显示的内容,l ...
- Linux下检测IP地址冲突及解决方法
问题说明:在公司办公网内的一台物理机A上安装了linux系统(ip:192.168.9.120),在上面部署了jenkins,redmine,svn程序.由于是在办公网内,这台机器和同事电脑都是在同一 ...
- Linux下控制器IO地址
在Linux下使用cat /proc/ioports可以查看控制器使用的IO地址范围
随机推荐
- dell T420热插拔安装过程
http://v.youku.com/v_show/id_XNTUzMjk4NTQw.html
- C++11 function
#include <iostream> #include <functional> #include <vector> using namespace std; / ...
- C#远程调用技术WebService修炼手册
一.课程介绍 一位伟大的讲师曾经说过一句话:事物存在即合理!意思就是说:任何存在的事物都有其存在的原因,存在的一切事物都可以找到其存在的理由,我们应当把焦点放在因果关联的本质上.所以在本次分享课开课之 ...
- Arcgis for JavascriptAPI 常用接口
转自原文arcgis for javascriptAPI常用接口 var map, navToolbar, editToolbar, tileLayer, toolbar; //var mapBase ...
- sql语句练习题
6.Mysql不要用top用limit 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢? 查找时Mysql不能用top,反正我用不了,查了下可以用limit来替换. 比 ...
- ios开发经常使用RGB色值
iOS中RGB经常使用的色值,同一时候可将对颜色的设置定义成宏,方便开发应用,如: // RGB颜色转换(16进制->10进制) #define UIColorFromRGB(rgbValue) ...
- 侏罗纪世界2百度云在线观看迅雷下载高清BT下载
原名:Jurassic World: Fallen Kingdom 地区:美国 语言:英语 首播:2018-06-15(中国大陆) / 2018-06-22(美国) 电视台: 类型:动作 / 科幻 / ...
- 美国谍梦第一季/全集The Americans迅雷下载
美国谍梦 第一季 The Americans Season 1 (2013)本季看点:这部背景设在80年代的剧集,故事讲述了一对被组织安排在美国生活的克格勃特工夫妻Phillip和Elizabeth, ...
- 副总统第一至三季/全集Veep迅雷下载
本季第一.二.三季 Veep Season 1 (2012-2014)看点:<副总统>讲述了Selina Meyer从一名参议员成为副总统后,开始面对成堆的突发状况,很快,她便认识到,成为 ...
- Git项目的初始化
快速设置— 如果你知道该怎么操作,直接使用下面的地址 git@github.com:username/myproject.git 我们强烈建议所有的git仓库都有一个README, LICENSE, ...