Getting Physical With Memory.CPU如何操作内存
原文标题:Getting Physical With Memory
原文地址:http://duartes.org/gustavo/blog/
[注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下。一来自己复习,二来与大家分享。]
在你试图理解一个复杂的系统时,如果能揭去表面的抽象并专注于最低级别的概念,往往会有不小的收获。在这个精神的指导下,让我们看看对于内存和I/O端口操作来说最简单、最基础的概念,即CPU与总线之间的接口。其中的细节是很多上层概念的基础,比如线程同步。当然了,既然我是个程序员,就暂且忽略那些只有电子工程师才会去关注的东西吧。下图是我们的老朋友,Core 2:
Core 2 处理器有775个管脚,其中约半数仅仅用于供电而不参与数据传输。当你把这些管脚按照功能分类后,就会发现这个处理器的物理接口惊人的简单。本图展示了参与内存和I/O端口操作的重要管脚:地址线,数据线,请求线。这些操作均发生在前端总线的事务上下文结构(the context of a transaction)中。前端总线事务的执行包含五个阶段:仲裁,请求,侦听,响应,数据操作。在执行事务的过程中,前端总线上的各个部件扮演着不同的角色。这些部件称之为agent。通常,agent就是全部的处理器外加北桥。
本文只分析请求阶段。在此阶段中,发出请求的agent往往是一个处理器,它输出两个数据包。下图列出了第一个数据包中最为重要的位,这些数据位通过处理器的地址线和请求线输出:
地址线输出指定了事务发生的物理内存起始地址。我们有33条地址线,他们指定了数据包的第35至第3位,第2至第0位为0。因此,实际上这33条地址线构成了一个36位的、以8字节对齐的地址,正好覆盖64GB的物理内存。这种设定从奔腾Pro就开始了。请求线指定了事务的类型。当事务类型为I/O请求时,地址线指出的是I/O端口地址而不是内存地址。当第一个数据包被发送以后,同样由这组管脚,在下一个总线时钟周期发送第二个数据包:
属性信号(attribute signal A[31:24])很有趣,它反映了Intel处理器所支持的5种内存缓冲功能。把这些信息发布到前端总线后,发出请求的agent就可以让其他处理器知道如何根据当前事务处理他们自己的cache,以及让内存控制器(也就是北桥)知道该如何应对。一块指定内存区域的缓存类型由处理器通过查询页表(page table)来决定,页表由OS内核维护。
典型的情况是,内核把全部内存都视为"回写"类型(write-back),从而获得最好的性能。在回写模式下,内存的最小访问单元为一个缓存线(cache line),在Core 2中是64字节。当程序想读取内存中的一个字节时,处理器会从L1/L2 cache读取包含此字节的整条缓存线的内容。当程序做写入内存操作时,处理器只是修改cache中的对应缓存线,而不会更新主存中的信息。之后,当真的需要更新主存时,处理器会把那个被修改了的缓存线整体放到总线上,一次性写入内存。所以大部分的请求事务,其数据长度字段都是11(REQ[1:0]),对应64 字节。下图展示了当cache中没有对应数据时,内存读取访问的过程:
在Intel计算机上,有些物理内存范围被映射为设备地址而不是实际的RAM存储器地址,比如硬盘和网卡。这使得驱动程序可以像读写内存那样,方便的与设备通信。内核会在页表中标记出这类内存映射区域为不可缓存的(uncacheable)。对不可缓存的内存区域的访问操作会被总线原封不动的按顺序执行,其操作与应用程序或驱动程序所发出的请求完全一致。因此,这时程序可以精确控制读写单个字节、字、或其它长度的信息。这都是通过设置第二个数据包中的字节使能掩码(byte enable mask A[15:8])来完成的。
前面讨论的这些基本知识还包含很多关联的内容。比如:
1、 如果应用程序想要尽可能高的运行速度,就应该把会被一起访问的数据尽量组织在同一条缓存线中。一旦这条缓存线被载入,之后的读取操作就会加快很多,不再需要额外的内存访问了。
2、 对于回写式内存访问,作用于一条缓存线的任何内存操作都一定是原子的(atomic)。这种能力是由处理器的L1 cache提供的,所有数据被同时读写,中途不会被其他处理器或线程打断。特别的,32位和64位的内存操作,只要不跨越缓存线的边界,就都是原子操作。
3、 前端总线是被所有的agent所共享的。这些agent在开启一个事务之前,必须先进行总线使用权的仲裁。而且,每一个agent都需要侦听总线上所有的事务,以便维持cache的一致性。因此,随着部署更多的、多核的处理器到Intel计算机,总线竞争问题会变得越来越严重。为解决这个问题,Core i7将处理器直接连接于内存,并以点对点的方式通信,取代之前的广播方式,从而减少总线竞争。
本 文讲述的都是有关物理内存请求的重要内容。当涉及到内存锁定、多线程、缓存一致性的问题时,总线这个角色又将浮出水面。当我第一次看到前端总线数据包的描 述时,会有种恍然大悟的感觉,所以我希望您也能从本文中获益。下一篇文章,我们将从底层爬回到上层去,研究一个抽象概念:虚拟内存。
参考: http://blog.csdn.net/drshenlei/article/details/4243733
Getting Physical With Memory.CPU如何操作内存的更多相关文章
- [转]检测SQLSERVER数据库CPU瓶颈及内存瓶颈
在任务管理器中看到sql server 2000进程的内存占用,而在sql server 2005中,不能在任务管理器中查看sql server 2005进程的内存占用,要用 以下语句查看sql se ...
- 服务器CPU繁忙或内存压力引起网络掉包的浅析与总结
最近一段时间遇到了两起有意思的故障,现象都是网络掉包或网络断开,不过这些只是表面现象,引起现象出现的本质才是我们需要关注的重点: 案例1: 平台 :VMware平台 操作系统 :Windows ...
- Motherboard Chipsets and the Memory Map.主板芯片组与内存映射
原文标题:Motherboard Chipsets and the Memory Map 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外 ...
- DMA(direct memory access)直接内存访问
DMA(Direct Memory Access),这里的 memory,指的是计算机的内存,自然与外存(storage)相对.这里的关键词在 Direct (直接),与传统的相对低效的,需要通过 C ...
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...
- EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载
EF如何操作内存中的数据和加载外键数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需 ...
- [hadoop] - Container [xxxx] is running beyond physical/virtual memory limits.
当运行mapreduce的时候,有时候会出现异常信息,提示物理内存或者虚拟内存超出限制,默认情况下:虚拟内存是物理内存的2.1倍.异常信息类似如下: Container [pid=13026,cont ...
- 使用python函数持续监控电脑cpu使用率、内存、c盘使用率等
方法一: # import time 导入time模块 # import psutil 导入psutil模块 # def func(): # while True: ------->持续监控得w ...
- 危险代码:如何使用Unsafe操作内存中的Java类和对象
危险代码:如何使用Unsafe操作内存中的Java类和对象—Part1 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part2 危险代码:如何使用Unsafe操作内存中的Java类和对 ...
随机推荐
- TypeScript 之 声明文件的发布
https://www.tslang.cn/docs/handbook/declaration-files/publishing.html 发布声明文件到npm,有两种方式: 与你的npm包捆绑在一起 ...
- ssh证书免认证登录
思路: 客户端私钥存放于客户端,/root/.ssh/id_rsa 将客户端公钥存放于要远程控制服务器上:将客户在公钥id_rsa.pub内容追加到 /root/.ssh/authorized_key ...
- const引用返回值
一.引用 引用是别名 必须在定义引用时进行初始化.初始化是指明引用指向哪个对象的唯一方法. const 引用是指向 const 对象的引用: ; const int &refVal = iva ...
- RedHat6.5安装zookeeper单机
版本号: Redhat6.5 zookeeper-3.4.6 JDK1.8 zookeeper下载 官网下载地址:https://mirrors.tuna.tsinghua.edu.cn/apac ...
- 需要序列化的类中没有写serialVersionUID的解决办法
由于没赋值serialVersionUID 只是警告,不是错误,造成先前没留意设定serialVersionUID,网络两端上线运行一段时间也感觉正常.如果再增减修改field,没赋值好serialV ...
- Go 缓冲信道和非缓冲信道
非缓冲信道是一个进一个出,再一个进再一个出,信道内是不保存数据的 缓冲信道是可以很多个依次进去,存储在信道里,然后一个一个的按次序取出来. 不过缓冲信道如果超过了预期的存入个数,会发生信道阻塞,只有把 ...
- linux进程监控和简单的重启&服务的创建 参考自http://blog.csdn.net/lockheed_hong/article/details/73549837
脚本文件 该脚本实现了一个检测进程是否存在,不存在的情况下重启进程并且记录日志. #! /bin/sh proc_name="console/queue/gift.php" # 进 ...
- mysql 性能
https://blog.csdn.net/zengxuewen2045/article/category/6388631 #sda 磁盘信息dstat -D sda 3 5 #找出系统瓶颈dstat ...
- [2]注解(Annotation)-- 深入理解Java:注解(Annotation)自定义注解入门
转载 http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 深入理解Java:注解(Annotation)自定义注解入门 要深入学习 ...
- 深度图像配准(Registration)原理
机器视觉中,3D相机产生的深度图像(depth image)通常需要配准(registration),以生成配准深度图像(registed depth image).实际上配准的目的就是想让深度图和彩 ...