The Trip of An Address -- An Outline
Jason Lee
[Scene 1. Code -> VA]
本文将以如下代码(ttoaa.c)为例,观察函数f入口地址的行程。
整篇文章的内容会涉及Linux和Windows两种不同系统的场景。
将以上代码在Windows上进行编译、链接,得到ttoaa.exe,运行输出:
由此可知道函数f的VA为0x00401000。那么,这个VA是怎么来的?
通过执行命令dumpbin /ALL ttoaa.exe > ttoaa.exe.dump,可以得到PE文件格式内容。
在Optional Header Values中可以看到image base为0x00400000,而base of code为1000,
所以可以知道代码段的起始位置为0x00401000,而函数f正好位于代码段起始位置。
参考ttoaa.exe.dump文件的内容,可以想象这个程序在内存中的布局可能如下图:
[ 图 - 1 ]
[Scene 2.TLB]
关于TLB的位置,我有点小疑惑:是在Segmentation之前还是之后呢?
后来我想,不论是从TLB的实际作用(VA -> PA),还是从目的(加快地址映射)来看,都应该在Segmentation前面。
现在获得了函数f的VA,CPU要执行相应代码,首先要获取第一条指令。
怎么获取这一条指令呢?首先看main函数:
前面就知道main函数的入口地址为0x00401020,从反汇编结果可以看出一进入main函数先保存栈顶指针,继而调用函数f。
现在CPU需要做的就是获取VA为0x00401000的指令,然后执行。
[ 图 - 2 ]
如上图,CPU的取指(Fetch)阶段会先访问TLB,看是否存在VA到PA的映射。
并且由于现在要获取的是指令,所以对应的是i-TLB,即Instruction TLB。
TLB全称为Translation Lookaside Buffer,存储着key-value映射,其中key为VA,value为PA。
由于是第一次访问0x00401000,所以i-TLB中还没有相关映射,需要继续进行地址映射,并把映射结果回填到i-TLB,以加速下次访问。
[Scene 3.Segmentation]
按理说,现在位于代码段中,VA需要加上CS指定的偏移量才能获得线性地址,不过Windows和Linux都采用Flat Model屏蔽了段机制,毕竟32位地址线足够指向整个4G空间。
所以,逻辑地址(或者说虚拟地址)即是线性地址。
为了实现Flat Model(地址平面化),只需要设置CS、DS两个段寄存器(指向GDT中的段描述符)相应的段描述符,将其基址设为0,段范围限制设为4G。
[Scene 4. Paging]
这里考虑的是页面大小为4KB的情况。
如果没有开启PAE,页式映射过程如下(参考Intel Software Developer Manual):
[ 图 - 3 ]
如果开启了PAE,页式映射过程如下:
[ 图 - 4 ]
[Scene 5. Cache]
昂贵的Cache本身就已经是为了尽量提高CPU的执行速度,消除CPU和内存之间的瓶颈,除此之外,芯片设计者为了提高查找缓存的速度,还将访问Cache和页式映射两件事设计成同时进行的——这利用了低位/页内地址在影射过程的不变形。
先了解下Cache的工作原理。
首先,Cache对于CPU给的地址有两种观察方式:Look-aside和Look-through。在前者模式下,Cache就是作为旁观者,类似抓了一个包过来观察的同时不影响原有的电路逻辑,直到HIT了才终止到内存寻找的逻辑;在后者模式下,Cache就作为必经之路,一定要先Cache判断为MISS后,才允许电路继续执行。
其次,Cache是由若干个Cache-line组成的,每一个Cache-line又分为Tag和Data,一列Cache-line称为一路(1-way)。
用Everest查看本机数据,得知L1-iCache为32KB:
从上图可以了解到L1 Cache有8路,每一路有64个Cache-line,每一个Cache-line分为24位的tag和64字节的数据部分。
这里可以发现每一路都是4K,对应着一个内存页面,于是可以产生一种良好(当然还有混乱的、只适合小缓存使用的全相联等方式,这里不讨论)的关联方式,每一个内存页相应的页内地址直接对应一个Cache-line。
根据页式映射[ 图 - 3 ]可以知道低12位是不变的,只在最后定位页内地址时才使用到。所以,在进行页式映射的同时,就可以利用地址的低位信息先确定缓存索引,等物理映射完成后,就不必再匹配索引了,直接利用高24位匹配Cache-line的tag。
如果上述tag和索引都匹配到了,那么地址的低6位就可以用来确定Cache-line中64字节的位置,进而获取数据。
[Scene 6. Memory]
如果Cache那边MISS了,就进一步来到了内存。
这时候由控制总线确定操作类型(比如读或写),然后由地址总线确定内存中的位置,再由数据总线来传输要读或者写的数据。
这些电平的传输就要靠我们拆开机箱、卸下风扇才能看到的芯片引脚了。
如果缺页了,就要进行换页了,由OS来控制。
[End]
结尾有点仓促,不过今天确实有点累(昨天去上海听演唱会,回来又熬夜写了下记录),也想这周一定要结束这一个系列的回顾学习,并以此篇作为一个学习小结,毕竟拖了有段时间了。
[参考资料]
1. Wikipedia
2. Gustavo Duarte
3. CSAPP
4. Linux内源源代码情景分析
5. Windows内核原理与实现
6. Intel Software Developer Manual
分享到:
相关推荐
scratch2源码小老鼠的旅程提取方式是百度网盘分享地址
位域(Bit Fields),也被称为位段,是C/C++中的一种特殊的数据结构,它允许在一个整数类型(通常是`unsigned int`)中定义一系列具有固定宽度的字段,每个字段占据一个或多个位。这种特性非常适用于硬件接口编程和...
【标题】"Developer-Starter:只是一些简单的事情,让我开始成为一名开发人员的旅程" 提示我们这是一个关于初学者入门编程的资源集合,特别强调了HTML作为基础学习的一部分。这通常意味着该压缩包可能包含一系列的...
一个即将推出的平台,供旅行者与来自世界各地的朋友和家人分享他们的旅程。 这个项目最初是在 2012 年夏天我在北欧和中欧旅行时设想的。 1.0 版的预计发布日期:12 月 15 日。 奇科州立大学奇科 CSCI 490 - 高级...
【标题】"我的旅程响应式网页模板"是一个专为展示个人旅行经历或旅游服务设计的网页模板。响应式设计是其核心特点,意味着这个模板能够根据用户设备的屏幕大小自动调整布局,提供良好的视觉体验,无论是桌面电脑、...
标题“一个报文的路由器之旅(V1.0)”揭示了我们即将探讨的主题——网络数据包在路由器中的处理和传输过程。这个过程包含了多个层面的技术,包括第二层(L2)和第三层(L3)的协议操作,以及服务质量(QoS)等关键...
计算每类地址的最大主机数时,需要减去全零(网络地址)和全一(广播地址)这两种特殊地址,这是为了确保每个网络至少有一个有效的主机地址。 IP地址的分配和管理随着互联网的发展,逐渐变得紧张。为解决这个问题,...
模板提供的 Demo 地址是用户查看和测试模板实际效果的入口,它可能包含了一个预设的示例旅程地图,供用户参考和学习。而 License 指的是 Arvin Xu 对该模板的版权信息,":registered:" 表明该模板可能遵循特定的开源...
无论是增加一张网卡还是购买家庭路由器,核心都在于通过一个设备将内部局域网和外部网络连接起来,并配置相应的IP地址和网关。 网络世界遵循着一套严密的规则,IP头便是这规则中的一项重要组成部分。IP头中的版本号...
在一个月的挑战中深入学习C++,这是一段激动人心的旅程。C++是一种强大的、通用的编程语言,以其高效性、灵活性和面向对象的特性而闻名。它不仅适用于系统编程,还可以用于游戏开发、软件工程等多个领域。在这个实例...
例如,如果有一个`int`变量`num`,声明一个`int* ptr`,那么`ptr`就指向`num`的地址,即`ptr`是一个指向`int`类型数据的指针。理解这一点有助于我们正确地访问和修改指针所指向的值。 接下来,我们要讨论的是“指针...
Postman不仅仅是一个简单的请求工具,更是一个全面的API测试套件。你可以为每个请求设置预期的响应状态码、头信息和数据,通过断言检查实际响应是否符合预期。此外,它支持创建测试集合,批量执行一组相关的API请求...
在C语言的学习旅程中,指针是一个绕不开的话题。作为编程语言中的核心概念之一,指针的掌握程度往往直接影响到一个程序员对计算机内存结构的理解和操作能力。指针不仅仅是一个存储数据地址的变量,它更是C语言中一种...
4. **处理结果**:无论使用哪种方法,我们都需要遍历返回的结果,通常只关心第一个IPv4地址(如果需要IPv6,可以选择第一个IPv6地址)。结果可以用`struct in_addr`(对于IPv4)或`struct in6_addr`(对于IPv6)表示...
Mac地址转换器 此Python程序旨在更改您的系统MAC地址 通过在进入网络之前运行python程序,您将能够使用其他mac地址来...每天您可能都走同样的旅程,并且可能登录到公共或私人网络,该网络节省了您之前几个赛季的访问量
在易语言中,创建对象时,系统会自动分配内存并返回一个句柄,这个句柄实际上就是对象在内存中的地址。 下面是一段简单的易语言源码,展示了如何获取类对象的地址: ```易语言 .定义 类 类名 .属性 属性1, 整数型...
好吧,你和你的女朋友约会了,你还年轻,而且你生活在一个交通繁忙的首都。 (显然你没有车,它太主流了)。 你想去某个地方,使用公共交通工具。 因此,像往常一样,您使用 Web 浏览器时,您会发现需要执行以下...
它允许我们将文本、图像、音频、视频等元素组织成...总的来说,"我的第一个HTML代码"是编程旅程的起点,虽然可能简单,但它开启了对网页制作世界的探索。通过不断学习和实践,我们可以创造出功能丰富、设计精美的网页。