数据库数据量很大大,逻辑不能在内存里做怎么办

Android逆向之旅---运行时修改内存中的Dalvik指令来改变代码逻辑
时间: 14:33:56
&&&& 阅读:188
&&&& 评论:
&&&& 收藏:0
标签:一、前言最近在弄脱壳的时候发现有些加固平台的加固方式是修改了dex文件结构,然后在加载dex到内存的时候,在进行dex格式修复,从而达到了apk保护的效果,那么在dex加载到内存的时候,如何进行dex格式的修复呢?其实原理就是基于运行时修改内存中的Dalvik数据,本文就来用一个简单的例子来介绍一下如何在内存中去修改Dalvik指令代码来改变代码本生的运行逻辑。在讲解本文之前,一定要先看这篇文章:&这篇文章主要介绍了关于Dex文件的格式介绍,这个对于后面修改内存中Dex的数据是有很大的作用的,如果没有阅读完这篇文章,或者是不了解Dex的文件格式的话,下面介绍的内容将会看的很吃力,因为本文不会在重复的介绍一下Dex的文件格式了。好了,下面就开始我们今天的介绍主题了。首先来说一下案例场景:本文的案例就是将一个类的方法改变他的运行逻辑,原来的逻辑是加法操作,现在改成乘法操作。二、案例介绍这里在TestAdd类中有一个加法的操作方法,然后我们在native层去修改Dalvik指令,修改这个方法为乘法操作这里我们可以看看TestAdd类的实现:只是一个简单的加法操作,下面来调用运行测试:测试结果如下:看到了测试结果,发现是乘法,而不是加法的结过,好了,到这里我们就演示完了项目结构,下面来开始说说如何修改的:三、代码解析这里把修改指令的逻辑代码放在了native层做的,其实放到Java层也是可以的,但是会发现在操作内存字节的时候,Java会显得很无力,因为他没有指针,指针真的很好很强大,特别是在操作文件和内存字节的时候,那写代码都很爽的。在MainActivity中定义了一个native方法:我们使用javah指令产生头文件:运行命令的时候,注意目录和类全名没有后缀。把产生的头文件拷贝到工程中:四、原理解析下面开始写主要逻辑了,在编写逻辑之前,这里我还是说一下Dex的文件格式,以及本文章需要用到的几个数据结构:第一个数据结构:Uleb128&LEB128 ( little endian base 128 ) 格式 ,是基于 1 个 Byte 的一种不定长度的编码方式 。若第一个 Byte 的最高位为 1 ,则表示还需要下一个 Byte 来描述 ,直至最后一个 Byte 的最高位为 0 。每个 Byte 的其余 Bit 用来表示数据 。这里既然介绍了uleb128这种数据类型,就在这里解释一下,因为后面会经常用到这个数据类型,这个数据类型的出现其实就是为了解决一个问题,那就是减少内存的浪费,他就是表示int类型的数值,但是int类型四个字节有时候在使用的时候有点浪费,所以就应运而生了,他的原理也很简单:图只是指示性的用两个字节表示。编码的每个字节有效部分只有低7bits,每个字节的最高bit用来指示是否是最后一个字节。非最高字节的bit7为0最高字节的bit7为1将leb128编码的数字转换为可读数字的规则是:除去每个字节的bit7,将每个字节剩余的7个bits拼接在一起,即为数字。比如:LEB128编码的0x02b0 —& 转换后的数字0x0130转换过程:0x02b0 =& 11 0000 =&去除最高位=& 000 0 =&按4bits重排 =& 00 00 =& 0x130底层代码位于:android/dalvik/libdex/leb128.h这个结构非常重要,也是后面所有结构的基础,而且在后面看解析代码中都会用到这个结构,知道他的原理,解析代码就很简单了。第二个数据结构:string_ids_itemstruct string_ids_item{ uint string_data_}这个结构主要是存储dex文件中所有的字符串的,其中的string_data_off字段是字符串在dex文件中的相对地址,每个字符串都是uleb128格式的,解析完每一个字符串都存放到一个字符串池中,这个池子中的字符串索引值StringIdIndex将会被下面几个数据结构使用到。类似于这样:第三个数据结构:type_ids_itemstruct type_ids_item{ uint descriptor_}这个数据结构,主要存储的是dex中所有类,方法等类型的id值,这里的descriptor_ids字段就是上面的字符串常量池中的索引值id,这里解析完之后也会存放在一个常量池中,给后续的数据结构使用,类似于这样:第四个数据结构:class_def_itemstruct class_def_item{ uint class_ uint access_ uint superclass_ uint interfaces_ uint source_file_ uint annotations_ uint class_data_ uint static_value_}这个数据结构主要存储的是dex中所有类的元信息,其中class_idx字段是一个TypeId类型的,就是上面的TypeId池子中的索引值,其他的字段不解释了,还有一个重要的字段就是class_data_off这个字段就是类数据在dex文件中的相对地址。解析结构类似于:第五个数据结构:method_id_itemstruct method_id_item{ ushort class_ ushort proto_ uint name_}这个数据结构主要存储的是dex中所有的方法元信息,其中class_idx字段是上面类数据结构中的class_idx,name_idx字段是在字符串池中的索引值id,这里解析完之后,也是需要用一个池子来存放这些MethodId索引值,下面的一些结构需要用到。解析结构类似于:第六个数据结构:class_data_itemstruct class_data_item{ uleb128 static_fields_ uleb128 instance_fields_ uleb128 direct_methods_ uleb128 virtual_methods_ encoded_field static_fields [ static_fields_size ]; encoded_field instance_fields [ instance_fields_size ]; encoded_method direct_methods [ direct_method_size ]; encoded_method virtual_methods [ virtual_methods_size ];}这个数据结构主要存储的是类中的具体信息,这里包括static字段,类字段,static方法,类方法等信息,这个数据结构数据在dex中的位置,就是上面的class_def_item数据结构中的class_data_off字段的地址。解析结构如下:第七个数据结构:encoded_methodstruct encoded_method{ uleb128 method_idx_ uleb128 access_ uleb128 code_}这个数据结构主要存放的是一个方法指令的元信息,method_idx_diff字段是上面的方法类型池中的索引值id,code_off字段就是这个方法存储的指令代码相对地址。解析结构如下:第八个数据结构:code_itemstruct code_item{ ushort registers_ ushort ins_ ushort outs_ ushort tries_ uint debug_info_ uint insns_ ushort insns [ insns_size ];
// optional try_item tries [ tyies_size ]; // optional encoded_catch_handler_ // optional}这个数据结构主要存储的就是方法的指令的具体信息,其中ins_size字段表示的是这个方法的参数个数,insns_size字段表示的是这个方法的指令条数,insns字段存储的就是指令内容,解析结构如下:到这里我们就介绍了完了上面的几种数据结构,下面来总结一下:首先用一张图来看看:1》首先介绍了Uleb128数据结构,这个数据结构是贯穿所有数据结构的,所以这个数据结构是最基本的。2》然后介绍了string_ids_item数据结构,这里需要把dex中所有的字符串解析出来存放在一个常量池中,后续的数据结构会通过索引值来获取。比如type_ids_item数据结构中的idx字段指向的就是这个索引值。3》然后介绍了type_ids_item数据结构,这里的字段主要就是指向字符串常量池的索引值,解析完这个数据结构之后也是需要用一个常量池存储索引值,后续的数据结构会通过索引值来获取,比如class_idx信息。4》然后介绍了class_def_item数据结构,这里的字段主要是类的具体数据的偏移地址,类的索引值class_idx(这个是通过TypeId池获取)。5》然后介绍了method_id_item数据结构,这里主要是开始解析方法id内容,其中name_idx字段是字符串常量池中的值(通过StringId池获取),以及这个方法所在类的class_idx值。6》然后介绍了class_data_item数据结构,这个结构主要存储的是这个类对应代码的元信息,其中direct_methods&thod字段和virtual_methods字段就是存储的是类对应的指令元信息。他们的结构是encoded_method。7》然后介绍了encoded_method数据结构,这个结构中主要存储的是这个方法对应的元信息,其中method_idx_diff字段是上面得到的Method类型的id常量池索引值,code_off字段是这个方法指令对应的相对地址。8》最后介绍了code_item数据结构,其中insns字段就是存储的是方法的指令数据。来看看各个数据结构之间的关系:这里就算全部解析完了本文需要用到的数据结构,以及这些结构相互引用关系,这里还需要注意的是:这里的一些结构的解析地址是存放在dex的头部信息中的:下面我们在看看代码怎么去实现它,首先我们通过上面的例子看到,有一个字符串索引常量池,而我们现在如果想改一个方法的指令代码的话,肯定得找到他对应的code_off地址即可,现在我们有的入口条件就是:方法名+类名,所以思路是这样的:类名=》字符串索引常量池=》类型TypeId=》类的定义元信息ClassDefItem=》类的代码元信息ClassDataItem方法名=》字符串索引常量池+类的TypeId=》方法Id方法Id+类代码元信息ClassDataItem=》方法的元信息EncodeMethod=》方法的指令代码结构Code有了这个思路,下面来看具体代码吧:第一步:获取应用的内存数据地址,读取/proc/pid/maps文件第二步:解析出dex文件的内存地址因为我们知道一个进程的maps内存中是有很多数据的,所以这里需要先找到dex数据对应的起始地址:下面看代码如何进行解析这个起始地址和结束地址:这里我们打印一下起始地址和结束地址:通过打印的信息,可以看到,我们上面在使用命令行去查看maps文件的时候是多个dex文件的,但是用代码去去的时候就是只有一个dex内容,但是不管怎么样,最终的起始地址和结束地址是一样。第三步:校验dex文件这里为什么说校验文件呢?因为在内存中存在的是odex文件了,这个文件其实是dex文件进行优化之后的产物,看一下odex文件的格式:这个文件格式定义在DexFile.h头文件中,源码位于:Android源码目录\dalvik\libdex\DexFile.h这里的u1类型就是一个字节,u4就是4个字节,那么头部大小就是:8+4*9=40.所以,我们得到上面的起始地址,是odex文件的地址,我们需要获取到dex文件的偏移地址,然后在进行dex文件的头部信息校验,这里主要是校验dex文件的魔数:dex\n35,注意中间有一个换行符哦:下面来看具体代码:这里首先需要获取系统的对其页面大小,一般都是0x1000,然后我们采用的是用内存的结束地址开始往前找,记得每次在校验dex的时候,需要考虑DexOptHeader的大小是40,每次叠加的大小是页面大小。调用findmagic方法来校验dex文件:注意魔数中间有一个换行符即可。第四步:获取方法和类的StringId索引值关于这里的getStrIdx方法这里不再说了,代码后面会给出地址的,通过类的名称和方法的名称获取他们的StringId值第五步:获取方法和类的TypeId索引值这里关于getMethodIdx方法这里不再说了,代码后面会给出地址的,通过类的StringId获取ClassTypeId,再通过ClassTypeId和方法的StringId获取方法的MethodTypeId值。第六步:获取ClassDefItem地址第七步:获取方法的指令代码这里主要获取指令的大小,然后在获取指令代码,打印出来,我们可以分析指令的含义,看一下打印的结果:这里打印了指令大小是3,那么指令字节长度就是3*2=6个字节,下面打印了指令的字节是:90 00 02 03 0F 00到这里,其实我们已经完成了从内存中读取一个方法指定的指令字节了,下面就来看看如何修改这个指令吧,其实在修改之前,我们肯定得先去看懂这指令的含义。一条指令其实组成部分就是:指令码+指令操作数,一般指令的头几个字节就是指令码,而且指令码是可以查阅的,这里需要参考:& 比如这里的90指令码:看到了,这里的90指令码就是对应的int类型的加法操作,而且看到指令的格式是:binop vAA,vBB,vCC,再看看这个指令的解释:意思是,vBB+vCC=vAA。那么看到方法的定义是,传入两个参数,还需要一个参数用来存放结算值,我们可以反编译apk得到方法的smali语法看看:看到了,smali语法就是和我们分析的一样,那么这里的指令分析结果:90&00 02 03 0F 00分析完了指令,下面我们可以修改了,这里把加法变成乘法,其实就是改变操作码:通过查阅,92代表乘法指令码,那么这里把90改成92即可,下面就来进行修改:但是在修改之前还需要做一件事,改变内存属性,因为一般数据被加载到内存中是不允许修改了,但是可以借助mprotect函数来进行修改即可,因为我们只要修改add方法指令,那么只需要修改这个方法所在内存的那一页进行修改即可,其他的地方不需要改成可写模式的,改完之后,在使用memcpy函数进行内存数据的覆盖即可:看到了,通过上面这么已修改之后,add方法就变成了乘法了,这就是我们在文章开始的时候演示的传入的是4,5得到的全是20不是9的原因了,到这里我们也成功的修改了内存中的方法指令,下面来总结一下:六、修改流程步骤总结1》首先是需要确定method的名字,也就是method字符串,再确定method所在class的名字,也就是class字符串。这确定了要修改的方法。2》把2个字符串到DexStringId结构的位置进行搜索,进而得到2个字符串在DexStringId中的索引序号。3》对于class字符串,再通过DexStrngId索引序号,到DexTypeId中搜索,得到class字符串在DexTypeId中的索引序号。4》还是class字符串,得到DexTypeId中的索引序号后,再到DexClassDef中搜索,就可以得到class的DexClassDef的位置。其中classDataOff字段记录了DexClassData偏移,这个结构里可以找到DexMethod结构。5》而对于method字符串,找到DexStringId索引后,再结合上面class的DexTypeId,可以确定DexMethodId的索引序号。6》 现在我们知道了DexMethodId的索引序号,也知道了存放DexMethod的位置,直接搜索就可以得到我们要找的DexMethod。这个结构里的codeoff指向了存放指令的位置。得到指令之后,我们在对照指令表,来阅读指令的含义,然后将指令码进行替换,修改内存为可读可写模式,最后再把修改之后的指令写到内存中。项目下载地址:七、存在的问题上面看到修改内存指令其实还是比较简单的,因为本文主要介绍如何修改内存指令原理,所以用一个简单的例子来进行说明,但是在实际的过程中有这么一个问题就是我们在修改一个比较复杂的方法指令的时候,如果出现增加或者减少指令的情况,那么我们的指令代码的偏移地址就会发生改变,这样就会很麻烦,需要进行dex结构修复了,而这部分工作将会变得很难。八、技术用途本文介绍了运行时修改内存的指令代码,其实有两个用途:第一个用途:就是在本文开始的时候说到了,现在很多加固平台会操作apk中的dex文件,修改他们的数据结构,比如ClassDefItem,然后在内存运行dex的时候在进行结构修复,这样就可以避免一些破解者破解apk的风险了。第二个用途:在设备root之后,可以注入到其他进程,然后修改其他进程的核心方法指令,从而达到一些自己想要的想过,但是上面也说道了,这种方式最大的问题是在修改指令之后,需要进行一定的修复,不然dex结构也是被改乱了,程序就会崩了。九、技术概要1、了解了Dex文件的几种数据格式2、DexOpt格式了解以及dex和odex之间的关系2、分析了如何通过类名和方法名找到其对应内存的指令代码,并且获取相对应的指令3、使用mprotect函数进行内存模式的修改4、Dalvik指令字节码的了解十、总结运行时修改内存中的指令代码思路其实很重要,而且对dex中各个数据结构的了解,所以本文的流程是:先了解dex中一些数据结构,然后在设想修改思路,找到内存中对应方法的地址,得到指令,然后进行修改覆盖即可。更多内容:关注微信公众号,最新Android技术实时推送标签:原文地址:http://blog.csdn.net/jiangwei/article/details/
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!什么是SDRAM的bank,什么是page?
我的图书馆
什么是SDRAM的bank,什么是page?
前很多人对内存Bank(电脑系统与内存之间数据总线的基本工作单位)都有一种误解,认为单面内存就是单Bank,双面内存就是双Bank的。其实这种观念是不对的,内存的Bank(指物理Bank)数和内存颗粒的面无关,它们之间有什么联系呢?要讲清这个问题,就要提到内存的逻辑Bank,下面就给大家介绍一下物理Bank和逻辑Bank的概念。在介绍之前,我们先简单看一下现在市场上的主流DRAM内存产品.现在市场上流行的内存主要有3种:SDRAM、DDR SDRAM及Rambus。其中Rambus内存的控制器和前两者不同,且内部Bank和前两者也不同,将在后面单独介绍。先主要介绍SDRAM和DDR SDRAM的Bank问题,因为SDRAM就内核、Bank结构而言,和DDR SDRAM没有什么区别,这里作为一个整体来讲。逻辑Bank及其结构内存芯片存储数据的基本单位是bit(位),而进行寻址的基本单位则是Byte(字节),一个Byte就等于8bit。大家知道,在平面坐标系中,要确定一个点就要先找到它的横坐标和纵坐标。而在内存中数据的定位也很相似,内存中的数据结构就是一个大的数据阵列,为了便于理解,我们把它假想成一个大的表格,前面我们提到的平面坐标系中的点,在这里我们可以理解为经过定位后的单元格,当然在一个单元格中不是只有1bit的数据,而是由多个bit组成一个组放在单元格内,这里一个单元格我们可以称作一个组,这个单元格的位数也就是内存逻辑Bank的位宽。在进行数据读取时,先进行行的选定,再进行列的选定,最后再从这个单元格中读取出所需要的数据。而这由许许多多的单元格组成的大表我们就可以理解成逻辑Bank,当然因为制造工艺及数据寻址的原因,不可能让这个表格无限大,一般内存芯片中都是将内存容量分成几个阵列来制造,即多逻辑Bank。随着内存芯片容量的不断增加,逻辑Bank数量也在不断增加,早期的16Mbit之类的芯片采用的还是两个逻辑Bank的设计,现阶段常见内存芯片的Bank一般为4个(不包括Rambus),这点大家可通过内存条的编码进行识别。内存芯片设计时在一个时钟周期内只允许对一个逻辑Bank进行操作(实际上内存芯片的位宽就是逻辑Bank的位宽),而不能对所有逻辑Bank同时操作。所以逻辑Bank的地址线是通用的,只要再有一个逻辑Bank编号加以区别就可以了。内存芯片的位宽决定了一次能从它那里读出多少数据,并不是内存芯片里所有单元的数据能够一次全部读出。为了加深大家对逻辑Bank的理解,我们来看看一个单芯片的逻辑Bank示意图这里不用过于注意结构细节,只需要看看4个内存阵列。从图中可以很清楚地看到这个芯片是一个Bank数为4的芯片,其列和行分别为4096和2048,而逻辑位宽是4bit,将这三者相乘就是这个逻辑Bank的容量,这里是48×4 bit =32Mb。再乘以Bank的数量,则芯片的容量就可以算出来了,这里很显然是4个Bank,那么芯片的容量就是128Mb了。用虚线框起来的就是一个完整的逻辑Bank。可见一个Bank由内存阵列、传感放大器、一个行解码器、一个列解码器组成。物理Bank了解了逻辑Bank后,接下来我们简单看看物理Bank,物理Bank的含义就是指内存和主板北桥芯片之间传递数据的通道,自586以后的CPU数据总线均为64bit位宽,而CPU一次只能对一个物理Bank进行访问,所以一般情况下我们就把64bit作为一个物理Bank(Physical Bank),在前面我们已经讲过了逻辑Bank,所以在这里我给大家讲一下如何自己算出物理Bank,大家就会非常好理解了。由于CPU一次只能打开一个物理Bank,在单芯片上也只能打开一个逻辑Bank,这样我们就知道逻辑Bank的位宽也就是单芯片的位宽了,OK,明眼人就会看出来,我们把芯片的数据宽度和芯片的数量相乘再除以64就得到了内存条的物理Bank数了,即内存的Bank数=数据宽度×芯片数量/64。现在大家初步明白了内存的物理Bank和内存的面数无关了吧?后面我还会举例说明。在大概了解了SDRAM和DDR内存的物理Bank及逻辑Bank之后,下面我们来简单了解一下Rambus的Bank情况。
TA的最新馆藏[转]&[转]&[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢什么是内存BANK
互联网 & 04-21 01:18:00 & 作者:佚名 &
关于内存Bank的探讨 目前很多人对内存Bank(电脑系统与内存之间数据总线的基本工作单位)都有一种误解,认为单面内存就是单Bank,双面内存就是双Bank的。其实这种观念是不对的,内存的Bank(指物理Bank)数和内存颗粒的面无关,它
关于内存Bank的探讨 目前很多人对内存Bank(电脑系统与内存之间数据总线的基本工作单位)都有一种误解,认为单面内存就是单Bank,双面内存就是双Bank的。其实这种观念是不对的,内存的Bank(指物理Bank)数和内存颗粒的面无关,它们之间有什么联系呢?
要讲清这个问题,就要提到内存的逻辑Bank,下面就给大家介绍一下物理Bank和逻辑Bank的概念。在介绍之前,我们先简单看一下现在市场上的DRAM内存产品.现在市场上的内存主要有:SDRAM、DDR SDRAM及Rambus。其中Rambus内存的控制器和前两者不同,且内部Bank和前两者也不同,将在后面单独介绍。先主要介绍SDRAM和DDR SDRAM的Bank问题,因为SDRAM就内核、Bank结构而言,和DDR SDRAM没有什么区别,这里作为一个整体来讲。逻辑Bank及其结构内存芯片存储数据的基本单位是bit(位),而进行寻址的基本单位则是Byte(字节),一个Byte就等于8bit。大家知道,在平面坐标系中,要确定一个点就要先找到它的横坐标和纵坐标。而在内存中数据的定位也很相似,内存中的数据结构就是一个大的数据阵列,为了便于理解,我们把它假想成一个大的表格,前面我们提到的平面坐标系中的点,在这里我们可以理解为经过定位后的单元格,当然在一个单元格中不是只有1bit的数据,而是由多个bit组成一个组放在单元格内,这里一个单元格我们可以称作一个组,这个单元格的位数也就是内存逻辑Bank的位宽。在进行数据读取时,先进行行的选定,再进行列的选定,最后再从这个单元格中读取出所需要的数据。而这由许许多多的单元格组成的大表我们就可以理解成逻辑Bank,当然因为制造工艺及数据寻址的原因,不可能让这个表格无限大,一般内存芯片中都是将内存容量分成几个阵列来制造,即多逻辑Bank。随着内存芯片容量的不断增加,逻辑Bank数量也在不断增加,早期的16Mbit之类的芯片采用的还是两个逻辑Bank的设计,现阶段常见内存芯片的Bank一般为4个(不包括Rambus),这点大家可通过内存条的编码进行识别。内存芯片设计时在一个时钟周期内只允许对一个逻辑Bank进行操作(实际上内存芯片的位宽就是逻辑Bank的位宽),而不能对所有逻辑Bank同时操作。所以逻辑Bank的地址线是通用的,只要再有一个逻辑Bank编号加以区别就可以了。内存芯片的位宽决定了一次能从它那里读出多少数据,并不是内存芯片里所有单元的数据能够一次全部读出。为了加深大家对逻辑Bank的理解,我们来看看一个单芯片的逻辑Bank示意图这里不用过于注意结构细节,只需要看看4个内存阵列。从图中可以很清楚地看到这个芯片是一个Bank数为4的芯片,其列和行分别为,而逻辑位宽是4bit,将这三者相乘就是这个逻辑Bank的容量,这里是×4 bit =32Mb。再乘以Bank的数量,则芯片的容量就可以算出来了,这里很显然是4个Bank,那么芯片的容量就是128Mb了。用虚线框起来的就是一个完整的逻辑Bank。可见一个Bank由内存阵列、传感放大器、一个行解码器、一个列解码器组成。
物理Bank了解了逻辑Bank后,接下来我们简单看看物理Bank,物理Bank的含义就是指内存和主板北桥芯片之间传递数据的通道,自586以后的CPU数据总线均为64bit位宽,而CPU一次只能对一个物理Bank进行访问,所以一般情况下我们就把64bit作为一个物理Bank(Physical Bank),在前面我们已经讲过了逻辑Bank,所以在这里我给大家讲一下如何自己算出物理Bank,大家就会非常好理解了。由于CPU一次只能打开一个物理Bank,在单芯片上也只能打开一个逻辑Bank,这样我们就知道逻辑Bank的位宽也就是单芯片的位宽了,我们把芯片的数据宽度和芯片的数量相乘再除以64就得到了内存条的物理Bank数了,即内存的Bank数=数据宽度×芯片数量/64。现在大家初步明白了内存的物理Bank和内存的面数无关了吧?后面我还会举例说明。在大概了解了SDRAM和DDR内存的物理Bank及逻辑Bank之后。
下面我们来简单了解一下Rambus的Bank情况。Rambus的Bank为了讲解方便,下面以PC800 Rambus为例。Rambus不再采用SDRAM和DDR内存的并联技术,而是采用了更先进的串联技术。就现阶段而言,PC800 Rambus使用400MHz的16位总线,在一个时钟周期内可以在上升沿和下降沿同时传输数据,实际操作频率为400MHz×2=800MHz,理论带宽为16bit×2×400MHz/8=1.6GB/s,再配合850主板芯片的双通道模式,可以达到3.2GB/s的数据带宽。这也是大家熟知的高带宽,而它最重要的优势在于其逻辑Bank上,就现阶段的主流 Rambus来说,其逻辑Bank数高达32个,拥有更多的Bank数则意味着具有较少的Bank冲突,寻址流更加短暂随意。另外还可以提高寻址命中率和降低潜伏周期。当然,更多的Bank也使Rambus的制作模具制造更复杂,也就增加了成本。于是RAMBUS随后又推出了4i 架构的DRDRAM──在每个颗粒芯片上只有4个Bank。
大家感兴趣的内容
12345678910
最近更新的内容IBM Knowledge Center502 Bad Gateway
502 Bad Gateway
openresty/1.11.2.2

我要回帖

更多关于 逻辑回归数据量 的文章

 

随机推荐