当前位置: 首页 > 编程日记 > 正文

Linux内存寻址

一.内存地址分类以及MMU介绍

对于程序员来说,可以简单的把内存地址理解为一种访问存储单元的内容的一种方式。而对于80x86系列微处理器来说,我们需要区分三种地址:

(1)逻辑地址

这种地址通常使用在机器语言里用于指定操作数或机器指令的地址。该类地址在著名的80x86分段体系架构中得到了很好体现,因此DOS程序员和windows程序员都不得不把他们的程序分成一段一段的(如代码段、数据段、堆栈段等等)。每一个逻辑地址都是由一个段(segment)和相对于段的实际起始地址的偏移地址(即offset 或 displacement)组成。

(2)线性地址(又称虚拟地址

一个32位的无符号整数就可用于描述4GB(2的32次方=4G)的内存地址空间,相当于4,294,967,296个内存单元。线性地址通常用16进制表示,大小范围为:0x00000000 ~0xffffffff。

(3)物理地址

该类地址用于寻址/访问内存芯片里的存储单元。它们对应于微处理器引脚到内存总线之间的电信号物理地址由一个32比特或38比特的无符号整数的16进制表示。

内存管理单元(MMU)可通过一个叫做段单元(segmentation unit)的硬件电路,将逻辑地址转换成线性地址;接着,通过一个叫做页单元(paging unit)的电路,再将线性地址转换成物理地址。如下图所示:

在有多个处理器的系统中,所有的CPU共享相同的内存。这就意味着,RAM芯片可能被相互独立的CPU们并发的访问。由于对RAM芯片的读操作和写操作都必须串行地执行,在总线和每个内存芯片之间添加了一个叫做内存仲裁器的硬件电路。这个电路的作用是:当RAM芯片处于空闲状态(这里的空闲,当然是指没有CPU在访问它)时,授权给CPU访问(俗称“放行”);当RAM芯片正忙(已经有CPU在使用该芯片)时,延迟(暂时禁止,即暂时“闭门谢客”)其他CPU对其访问。

甚至单处理器系统中,也会使用内存仲裁器。这是因为这些系统包括特殊的处理器------DMA控制器,它与CPU也存在并发操作的情况。当然,多处理器系统中的内存仲裁器电路更为复杂,因为它有更多的输入端口。例如,双核奔腾在每个芯片的入口维护了一个双端口的仲裁器,并且要求两个CPU在使用公用的总线时必须交换同步消息。从编程的角度看,仲裁器是隐而不见的,因为它是完全由硬件电路管理的。

二.逻辑地址到虚拟地址的转换

1.段选择符和分段寄存器

一个逻辑地址包括两部分:段标识符 和 段内相对偏移地址。段标识符是一个被叫做段选择符(selector)的16比特的域,而偏移地址是一个32比特的域。

为了方便快速检索段选择符,处理器提供了6个分段寄存器(segmentation register)来缓存段选择符,它们是:cs,ss,ds,es,fs和gs. 虽然只有这6个寄存器,但程序可以复用同一个寄存器来实现不同的目的,只需要把该寄存器的内容保存到内存中,在随后需要的时候可以恢复它的内容。需要注意的是,cs、ss、ds有专门的用途。请看下面介绍:

cs-----内存段寄存器,指向含有代码指令的段;cs寄存器还有一个重要的功能:用于区分用户模式和内核模式,它包含一个指定当前优先级别(CPL, current priviledge level)的的2比特的域。如果该域的值为0,表明优先级最高;如果该值为3,表明最低的优先级。 Linux只使用了0和3,用以区分内核模式和用户模式。

ss-----堆栈段寄存器,指向包含当前程序栈的段;

ds-----数据段寄存器,指向包含静态和全局数据的段。

其它三个,即es,fs和gs,都是通用分段寄存器,可以指向任意类型的段。

2.段描述符

每一个段都由一个8字节的段描述符来表示,它描述了段的特征。段描述符要么存储在全局描述符表(GDT)里,要么存储在本地描述符表(LDT)里.

通常只定义了一个GDT。然而,每个进程都允许有自己的LDT,如果进程需要额外创建除了GDT里描述的之外的段。主存里GDT的地址和大小都包含在gdtr控制寄存器中,而当前正在使用的LDT的地址和大小则包含在ldtr控制寄存器中。

BASE:段的第一个字节的线性地址。

G:如果为0,则段的大小用字节表示。

Limit:保存了段中最后一个存储单元的偏移值,因此与segment的长度、大小是绑定在一起的。如果G为0,则LIMIT的大小范围为1字节~1MB;反之, LIMIT大小范围为4KB~4GB.

S:如果为0,表示为一个系统段(system segment);反之,为一个普通的数据段或代码段。系统段里保存了关键的数据结构,如LDT.

Type:描述segment的类型。

DPL:描述符优先级别。主要用于对segment的访问进行限制。

P:描述段是否在内存中存在的标记。

3.对段描述符的快速访问的实现

我们知道,逻辑地址由一个16比特的段选择符和一个32比特的偏移地址组成。同时,我们也知道,分段寄存器里只存储了段选择符。

我们先接着第一节继续对段选择符进行分析。它的格式如下所示:

Index:标记了GDT或LDT中段描述符的入口。由于段寄存器有8个字节长,它在GDT或LDT中的相对地址是这样来计算的:13个bit之长(如上图,比特3-15位)的index域值乘以8. 假设GDT位于0x00020000 (该值存放在gdtr控制寄存器中) 并且 段选择符的index域值为2,那么相应的段描述符的地址是这么来计算的:

0x00020000 +(2 x8),0x00020010.

TI: table indicator。TI=0,表示段描述符位于GDT中;TI=1,表示段描述符位于LDT中。

RPL:Requestor Previlige Level请求者优先级。

为了加快逻辑地址到线性地址的转换过程,80x86增加了一个不可编程的寄存器。

每当一个段选择符被加载到分段寄存器中时,相应的段描述符也被从内存里加载到那个匹配的不可编程的CPU寄存器中。这样,逻辑地址的转换就不再需要访问主内存中的GDT和LDT,而只需要访问那个包含段描述符的不可编程的寄存器。只有在分段寄存器内容改变时,才需要访问LDT或GDT。

3.分段单元实现逻辑地址到线性地址的转换

我们知道,内存管理单元(MMU)可通过一个叫做分段单元(segmentation unit)的硬件电路,将逻辑地址转换成线性地址;接着,通过一个叫做分页单元(paging unit)的电路,再将线性地址转换成物理地址。如下图所示:

那么,这个分段单元是按照什么样的流程完成自己的职责所在呢?

首先,它会检查段选择符的TI域,进而知道是哪个描述表存放了相应的段描述符。如果段描述符位于GDT,则分段单元从gdtr寄存器中读取GDT的线性基地址;否则,分段单元从ldtr读取LDT的线性基地址。

其次,根据上一步得到的线性基地址和段选择符的index域,计算出段描述符的地址。计算方法可参考上节。

通过以上两步,我们就可以定位到我们需要的段描述符。

最后,把逻辑地址的偏移与前面定位到的段描述符的线性地址BASE域相加,得到线性地址。这样,整个逻辑地址到线性地址的转换过程就成了

地址转换的过程如下图所示:

注意,本文中的线性地址跟虚拟地址是一个概念。

Smith先生版权所有,出处:http://blog.csdn.net/acs713/article/details/7950414

相关文章:

iptables 基本命令使用举例

原文地址:http://www.linuxsky.org/doc/admin/200803/262.html 一、链的基本操作 1、清除所有的规则。 1)清除预设表filter中所有规则链中的规则。 # iptables -F 2)清除预设表filter中使用者自定链中的规则。 #iptables -X #iptables -Z 2、…

重磅!教育部再次审批179所高校新增本科AI专业

整理&责编 | 夕颜出品 | CSDN(ID:CSDNnews)好消息!2 月 21 日,教育部官网发布了《教育部关于公布 2019 年度普通高等学校本科专业备案和审批结果的通知》,公开了 2019 年度普通高等学校本科专业备案和审批结果。17…

Qt之自定义搜索框

简述 关于搜索框,大家都经常接触。例如:浏览器搜索、Windows资源管理器搜索等。 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定。 简述效果细节分析Coding源码下载效果 细节分析 实现细节需要如下步骤&…

大型网站架构演变和知识体系

存爱好,作为收藏,原地址:http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html,同时向原创致敬之前也有一些介绍大型网站架构演变的文章,例如LiveJournal的、ebay的,都是非常值得参考的&#…

Python数据清理终极指南(2020版)

作者 | Lianne & Justin译者 | 陆离出品 | AI科技大本营(ID:rgznai100)一般来说,我们在拟合一个机器学习模型或是统计模型之前,总是要进行数据清理的工作。因为没有一个模型能用一些杂乱无章的数据来产生对项目有意义的结果。…

内存地址转换与分段

原文标题:Memory Translation and Segmentation 原文地址:http://duartes.org/gustavo/blog/ 翻译地址:http://blog.csdn.net/drshenlei/article/details/4261909 本文是Intel兼容计算机(x86)的内存与保护系列文章的第…

c++ 普通高精减

//c 普通高精减 //codevs 3115 高精度练习之减法 //内容简单&#xff0c;就不注释了。 //注意下&#xff0c;&&优先级高于||。 #include<cstdio>#include<cstring>char s1[600],s2[600];int a1[600],a2[600],len1,len2,i;int main(){scanf("%s",…

腾讯提超强少样本目标检测算法,公开1000类检测训练集FSOD | CVPR 2020

作者 | VincentLee来源 | 晓飞的算法工程笔记不同于正常的目标检测任务&#xff0c;few-show目标检测任务需要通过几张新目标类别的图片在测试集中找出所有对应的前景。为了处理好这个任务&#xff0c;论文主要有两个贡献&#xff1a;提出一个通用的few-show目标检测算法&#…

Linux加入到Windows域 收藏

一、实验环境&#xff1a; AD server&#xff1a;windows server 2003samba&#xff1a;redhat as5AD server的hostname和IP地址&#xff1a;turbomai-c<?xml:namespace prefix st1 ns "urn:schemas-microsoft-com:office:smarttags" />89f91.test.com 192…

哈希函数原理及实现

哈希解决冲突 1000以内的素数 一般的hash实现已经总结出一些比较重要的素数&#xff1a; static unsigned int table_size[] {7,13,31, 61, 127, 251, 509, 1021,2039, 4093, 8191, 16381, 32749, 65521,1310…

基于Virtual DOM与Diff DOM的测试代码生成

尽管是在年末&#xff0c;并且也还没把书翻译完&#xff0c;也还没写完书的第一稿。但是&#xff0c;我还是觉得这是一个非常不错的话题——测试代码生成。当我们在写一些UI测试的时候&#xff0c;我们总需要到浏览器去看一下一些DOM的变化。比如&#xff0c;我们点击了某个下拉…

Win32 环境下的堆栈

原文已经找不到&#xff0c;作者应该是&#xff1a;http://blog.csdn.net/slimak 但是没有找到此文&#xff0c;其中丢了2幅图 简介 在Win32环境下利用调试器调试应用程序的时候经常要和堆栈(Stack)打交道,尤其是在需要手工遍历堆栈(Manually Walking Stack)的时候我们需要…

在VMWare中配置SQLServer2005集群 Step by Step(四)——集群安装

在VMWare 中配置集群 1. 进入command 命令窗口执行以下命令&#xff0c;创建仲裁磁盘和共享数据磁盘 vmware-vdiskmanager.exe -c -s 200Mb -a lsilogic -t 2 F:\VM\Share\Windows\SQLServer\quorum.vmdk vmware-vdiskmanager.exe -c -s 4Gb -a lsilogic -t 2 F:\VM\Share\Wind…

口罩检测识别率惊人,这个Python项目开源了

作者 | 一颗小树x&#xff0c;CSDN 博主编辑 | 唐小引来源 | CSDN 博客昨天在 GitHub 上看到一个有趣的开源项目&#xff0c;它能检测我们是否有戴口罩&#xff0c;跑起程序测试后&#xff0c;发现识别率挺高的&#xff0c;也适应不同环境&#xff0c;于是分享给大家。首先感谢…

CentOS搭建msmtp+mutt实现邮件发送

1&#xff1a;搭建配置msmtp下载msmtp包&#xff1a;官方地址&#xff1a;http://msmtp.sourceforge.net/download.html编译&#xff0c;安装(官方下载的包为tar.xz格式):#xz -d msmtp-1.6.3.tar.xz #tar -xvf msmtp-1.6.3.tar #cd msmtp-1.6.3 #./configure --prefix /opt/app…

Linux环境下的堆栈--调试C程序

完整的调试过程&#xff0c;跟踪堆栈变化&#xff0c;32位下。 注意64位和此不同。 a.c代码&#xff1a; #include <stdio.h> int main() { AFunc(5,6);return 0; } int BFunc(int i,int j) {int m 1;int n 2;m i;n j; return m; }int AFunc(int i,int j) {…

听说过代码洁癖,Bug洁癖怎么解?

来源 | Python编程时光&#xff08;ID: Cool-Python&#xff09;当我们写的一个脚本或程序发生各种不可预知的异常时&#xff0c;如果我们没有进行捕获处理的时候&#xff0c;通常都会致使程序崩溃退出&#xff0c;并且会在终端打印出一堆 密密麻麻 的 traceback 堆栈信息来告诉…

POJO、VO、PO、FormBean区别:

首先讲一下四者的概念 POJO&#xff1a;Pure Old Java Object&#xff0c;符合Java Bean属性规范的简单Java对象&#xff0c;通常也称为VO&#xff08;Value Object&#xff0c;值对象&#xff09;。 VO&#xff1a;就是POJO; PO: Persistent Object&#xff0c;持久化对…

oracle中的sql%rowcount,sql%found、sql%notfound、sql%rowcount和sql%isopen

Oracle 存储过程 删除表记录时删除不存在的记录也是显示删除成功 create or replace procedure delDept(p_deptno in dept.deptno%type) is begindelete from dept where deptnop_deptno;dbms_output.put_line(部门删除成功...);exception when others thendbms_output.put_lin…

linux平台的链接与加载

原文是上下两篇 链接与加载(上) — 静态链接链接与加载(下) — 动态链接 为观看方便&#xff0c;现在合并起来。 一.静态链接 示例程序 我们先看一个简单的示例程序&#xff0c;代码如下&#xff1a; /*main.c*/int u 333;int sum(int, int);int main(int argc, char* argv…

预训练模型ProphetNet:根据未来文本信息进行自然语言生成

作者 | 刘大一恒、齐炜祯、晏宇、宫叶云、段楠、周明来源 | 微软研究院AI头条&#xff08;ID:MSRAsia&#xff09;编者按&#xff1a;微软亚洲研究院提出新的预训练模型 ProphetNet&#xff0c;提出了一种新的自监督学习目标——同时预测多个未来字符&#xff0c;在序列到序列的…

模拟进程管理小结,编码规范的重要性

废话不多说了&#xff0c;省的又有衰人找我麻烦。希望我讨厌的&#xff0c;和讨厌我的少来骚扰我&#xff0c;由衷的感谢它们。 我不回那些骚扰&#xff0c;是因为我见到名字就直接删了&#xff0c;看都懒的看了。也别怪我粗鲁&#xff0c;因为我一向是对什么人说什么话 的&…

JSPServlet路径问题

2019独角兽企业重金招聘Python工程师标准>>> 如果带WebRoot&#xff0c;那么js、css、img都应该放到WebRoot目录下&#xff0c;否则访问会有问题。千万不要放在WEB-INF下&#xff0c;因为WEB-INF下的内容只有服务器转发可以访问到&#xff0c;出于安全考虑。 如果不…

Git学习教程(六)Git日志

第六课 Git 日志 内容提要&#xff1a;浏览项目历史&#xff0c;查询指定提交内容&#xff0c;图形化显示分枝和合并...git log是git中最常用的一个命令&#xff0c;执行之后&#xff0c;会显示该项目的提交历史。如果命令不加任何参数&#xff0c;那么就会显示目前所在分枝上&…

汇编包含C代码

反汇编的时候带上C代码便于观察 比较三元表达式和if else的差异 a1.c #include <stdio.h> int main(void) { int a1;int b2;int c0;a (b>c)?1:0;return 0;} a2.c #include <stdio.h> int main(void) { int a1;int b2;int c0;if(b>c){a1;}else{a0;…

无需3D运动数据训练,最新人体姿势估计方法达到SOTA | CVPR 2020

作者 | Muhammed Kocabas译者 | 刘畅出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;人体的运动对于理解人的行为是非常重要的。尽管目前已经在单图像3D姿势和动作估计方面取得了进展&#xff0c;但由于缺少用于训练的真实的3D运动数据&#xff0c;因此现有的基于视频…

Linux内核跟踪之trace框架分析【转】

转自&#xff1a;http://blog.chinaunix.net/uid-20543183-id-1930846.html------------------------------------------本文系本站原创,欢迎转载!转载请注明出处:http://ericxiao.cublog.cn/------------------------------------------一: 前言本文主要是对trace的框架做详尽…

写给Python开发者:机器学习十大必备技能

作者 | Pratik Bhavsar译者 | 明明如月&#xff0c;编辑 | 夕颜来源 | CSDN&#xff08;ID:CSDNnews&#xff09;有时候&#xff0c;作为一个数据科学家&#xff0c;我们常常忘记了初心。我们首先是一个开发者&#xff0c;然后才是研究人员&#xff0c;最后才可能是数学家。我…

Linux环境程序栈溢出原理

当在缓冲区中输入过多的数据时&#xff0c;缓冲区溢出就会发生&#xff0c;C语言提供了多种方法&#xff0c;可以使在缓冲区中输入的数据比预期的多。 局部变量可以被分配到栈上。这就意味着在栈的某个地方有一个固定大小的缓冲区。 而栈是向下增长的&#xff0c;而且一些重要…

[翻译]Joomla 1.5架构(十一) model 包

这个包包含了跟数据表交互的所有相关类 JModel This abstract class is the base class for all Joomla! data access objects. 所有数据访问类的抽象基类。 以下的类都分别实现对不同表的访问&#xff0c;不再翻译了。 Adapter Folder JModelCategory This is a data access …