内存对齐规则

内存对齐规则
内存对齐规则

C语言中内存对齐规则讨论(struct)

(2012-02-17 17:51:17)

转载▼

分类:学习

标签:

struct

union

c语言

内存

it

对齐:

现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就是需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

对齐的作用:

各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存储。其他平台可能没有这种情况,但是最常见的是如果不按照合适其平台的要求对数据进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶数地址开始,如果一个int型(假设为32位)如

果存放在偶数开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次独处的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。

对齐的实现

通常我们写程序的时候,不需要考虑对齐问题,编译器会替我们选择适合目标平台的对齐策略。当然,我们也可以通知给编译器传递预编译指令而改变对制定数据的对齐方法。缺省情况下,编译器为结构体的每个成员按其自然対界条件分配空间。各个成员按照他们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。自然対界即默认对齐方式,是指按结构体的成员中size最大的成员对齐。

最常见的就是struct数据结构的sizeof的结果出乎意料。

结构体的sizeof的值并不是简单的将其中各个元素所占的字节相加,而是要考虑到存储空间的字节对齐问题

结构体默认的字节对齐准则:

1.结构体变量的首地址能够被其最宽基本类型成员的大

小所整除;

2.结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字符;

3.结构体的总大小为结构体最宽基本类型成员大小和编译器缺省対界条件大小中比较小得那个值的整数倍,如有需要编译器会在最后一个成员之后加上填充字节;

一结构体长度的求法:

A.成员都相同时(或含数组且数组数据类型同结构体其他成员数据类型)

结构体长度=成员数据类型长度*成员个数;

结构体中数组长度=数组数据类型长度*数组元素个数;B.成员不同

第一步:结构体的首地址有系统自动分配我们不予考虑

第二步:计算第一个成员变量的大小

第三步:计算第二个成员变量的大小,此时要注意此成员变量的偏移量(距离结构体首地址的长度)要保证是此变量大小的整数倍,如果不够则补空位;

依次计算所有成员变量,并求和。

第四步:选出所有成员变量中长度最长的变量的值,此时要保证总和是此变量长度的整数倍。如果不是则在最后面补空位。

注意:结构体作为成员时,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

例题一、

struct test1

{

char a;

int b;

double c;

bool d;

};

则sizeof(test1)值为24

内存结构为 1*** 1111 11111111 1*******(其中*为补空位)

例题二、

struct test2

{

char a;

struct test1 bb;

int c;

};

则sizeof(test2)的值为40

首先求a大小为1,在求bb时我们需要考虑偏移量,此时我们使用的bb的对比值并不是24而是test1中的最长值8,因此在字符a后需要补空位7位

然后加上bb长度24,

再计算c并加上其长度4.此时一共长36.

最后我们要注意原则中的第三条。在test2中最长的是结构体类型bb中的double,故总长度应该是8的整数倍。所以最后补位4位,得到40

内存结构为 1******** 1*** 1111 11111111

1******* 1111****(其中*为补空位)

例题三、

Struct test3

{

Char a;

Int b[4];

};

此时计算sizeof(test3)为20

内存结构为1*** 1111 1111 1111 1111

二、对齐规则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数32位机上是8)。程序员可以通过预编

译命令#pragma pack(n),n=1,2,4,8,16 来改变这一系数,其中的n 就是你要指定的“对齐系数”。

指定対界:

一般的,可以通过下面的方法来改变缺省的対界条件:

使用伪指令#pragma pack(n),编译器将按照n个字节对齐;

使用伪指令#pragma pack(),取消自定义的字节对齐方式;

注意:如果#pragma pack(n)中指定的n大于结构体中最大的成员的size,则其不起作用,结构体仍然按照size最大的成员进行対界。

规则1:

数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset

为0 的地方,以后每个数据成员的对齐按照#pragma pack 指定的数值和这个数据成员自身长度中,比较小的那个进行。

规则2:

结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进

行对齐,对齐将按照#pragma pack 指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

规则3:

结合1、2 颗推断:当#pragma pack 的n 值等于或超过所有数据成员长度的时候,这个n

值的大小将不产生任何效果。

试验

我们通过一系列例子的详细说明来证明这个规则吧!

我试验用的编译器包括GCC 3.4.2 和VC6.0 的C 编译器,平台为Windows XP + Sp2。

我们将用典型的struct 对齐来说明。首先我们定义一个struct:

#pragma pack(n)

struct test_t

{

int a;

char b;

short c;

char d;

};

#pragma pack(n)

首先我们首先确认在试验平台上的各个类型的size,经验证两个编译器的输出均为:

sizeof(char) = 1

sizeof(short) = 2

sizeof(int) = 4

我们的试验过程如下:通过#pragma pack(n)改变“对齐系数”,然后察看sizeof(struct test_t)的值。

1、1字节对齐(#pragma pack(1))

输出结果:sizeof(struct test_t) = 8 [两个编译器输出一致]

分析过程:

1)成员数据对齐

#pragma pack(1)

struct test_t {

int a;

char b;

short c;

char d;

};

#pragma pack()

成员总大小=8

2)整体对齐

整体对齐系数= min((max(int,short,char), 1) = 1

整体大小(size)=$(成员总大小) 按$(整体对齐系数) 圆整= 8 [注1]

2、2字节对齐(#pragma pack(2))

输出结果:sizeof(struct test_t) = 10 [两个编译器输出一致]

分析过程:

1)成员数据对齐

#pragma pack(2)

struct test_t {

int a;

char b;

short c;

char d;

};

#pragma pack()

成员总大小=9

2)整体对齐

整体对齐系数= min((max(int,short,char), 2) = 2

整体大小(size)=$(成员总大小) 按$(整体对齐系数) 圆整= 10

3、4字节对齐(#pragma pack(4))

输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]

分析过程:

1)成员数据对齐

#pragma pack(4)

struct test_t {

int a;

char b;

short c;

};

#pragma pack()

成员总大小=9

2)整体对齐

整体对齐系数= min((max(int,short,char), 4) = 4

整体大小(size)=$(成员总大小) 按$(整体对齐系数) 圆整= 12

4、8字节对齐(#pragma pack(8))

输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]

分析过程:

1)成员数据对齐

#pragma pack(8)

struct test_t {

int a;

short c;

char d;

};

#pragma pack()

成员总大小=9

2)整体对齐

整体对齐系数= min((max(int,short,char), 8) = 4

整体大小(size)=$(成员总大小) 按$(整体对齐系数) 圆整= 12

5、16字节对齐(#pragma pack(16))

输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]

分析过程:

1)成员数据对齐

#pragma pack(16)

struct test_t {

int a;

char b;

short c;

char d;

};

#pragma pack()

成员总大小=9

2)整体对齐

整体对齐系数= min((max(int,short,char), 16) = 4

整体大小(size)=$(成员总大小) 按$(整体对齐系数) 圆整= 12

操作系统内存管理复习过程

操作系统内存管理

操作系统内存管理 1. 内存管理方法 内存管理主要包括虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。 2. 连续分配存储管理方式 连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。 2.1 单一连续存储管理 在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和 DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内

存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。 2.2 分区式存储管理 为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。 分区式存储管理引人了两个新的问题:内碎片和外碎片。 内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。 为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。

分区式存储管理常采用的一项技术就是内存紧缩(compaction)。 2.2.1 固定分区(nxedpartitioning)。 固定式分区的特点是把内存划分为若干个固定大小的连续分区。分区大小可以相等:这种作法只适合于多个相同程序的并发执行(处理多个类型相同的对象)。分区大小也可以不等:有多个小分区、适量的中等分区以及少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区。 优点:易于实现,开销小。 缺点主要有两个:内碎片造成浪费;分区总数固定,限制了并发执行的程序数目。 2.2.2动态分区(dynamic partitioning)。 动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小。与固定分区相比较其优点是:没有内碎

产品命名规则

Cisco网络设备命名规则 CISCO 开头的产品都是路由器; 2. RSP 开头的都是CISCO7500 系列产品的引擎; 3. VIP 开头的产品都是CISCO 7500系列产品的多功能接口处理器模块; 4. PA 开头的产品都是CISCO 7500/7200系列产品的模块; 5. NPE 开头的都是CISCO7200 系列产品的引擎; 6. NM 开头的都是CISCO低端路由器模块; 7. WIC 开头的都是CISCO低端路由器的广域网接口模块; 8. VWIC 开头的都是CISCO低端路由器的语音接口模块; 9. WS-C 开头的产品都是交换机; 10. WS-X 开头的产品是交换机的引擎或模块; 11. WS-G 开头的产品是交换机的千兆光纤模块。 关键字: TT:适用2960 CE500交换机,表示电口 TC:适用2960 CE500交换机,表示电口+双介质口 LC:适用CE500,包括POE+电口+2SFP TS:适用3560,3750 表示电口+SFP PS:适用3560,3750 表示POE+SPF T:适用3750,仅电口 TD:适用3750,表示电口+10GBE cisco路由的命名规则都是以CISCO开头比如:cisco1721,cisco2621,ci sco3662,cisco3745。这些都是路由器。 比如:cisco2621 其中cisco:是品牌,前两位数字是系列号,这款产品属于2600系列, 后两位是具体的型号。 其中cisco 路由器有以下几个系列: cisco2500系列:cisco2501、cisco2502、一直到cisco2514,这些都是国 内能见到的设备,再往上就是国外的了,国内很少见到。 cisco1700:1720、1721、1751、1760 cisco1800:1821、1841 cisco2600系列:2610、2611、2620、2621、2651 cisco2600XM 系列:2610XM、2611XM、2620XM、2621XM cisco3600:3620、3640、3660 cisco3700:3725、3745 cisco3800:3825、3845 cisco7200:7204、7206、7204VXR、7206VXR这些都是机箱,使用当中 需要引擎的支持(NPE-225、NPE-300、NPE-400、NPE-G1、最新的是NP E-G2)和业务模块的支持东西很多了,这就不写了。 cisco7500:7507、7513 同样也需要引擎的支持(RSP2、RSP4、RSP8、 RSP16)和业务模块的支持,7200上的业务模块都能在75上使用,需要一块VIP 卡的支持。 在上面就是12000 系列:12008,12016这些是目前最高端的。同样也需要

内存对齐方式

对齐方式 为什么会有内存对齐? 在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间;各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。在缺省情况下,C编译器为每一个变量或数据单元按其自然对界条件分配空间。 字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。 一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。 某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。 影响结构体的sizeof的因素: 1)不同的系统(如32位或16位系统):不同的系统下int等类型的长度是变化的,如对于16位系统,int的长度(字节)为2,而在32位系统下,int的长度为4;因此如果结构体中有int等类型的成员,在不同的系统中得到的sizeof值是不相同的。 2)编译器设置中的对齐方式:对齐方式的作用常常会让我们对结构体的sizeof 值感到惊讶,编译器默认都是8字节对齐。 对齐: 为了能使CPU对变量进行高效快速的访问,变量的起始地址应该具有某些特性,即所谓的“对齐”。例如对于4字节的int类型变量,其起始地址应位于4字节边界上,即起始地址能够被4整除。变量的对齐规则如下(32位系统)

解决系统内存不能为 Read 的方法(新添附件,不断收集中……)

运行某些程序的时候,有时会出现内存错误的提示,然后该程序就关闭。 “0x????????”指令引用的“0x????????”内存。该内存不能为“read”。 “0x????????”指令引用的“0x????????”内存,该内存不能为“written”。 总结我见过的内存不能为Read 问题,问题原因可以归纳为以下几点: 1、驱动不稳定,与系统不兼容,这最容易出现内存不能为Read 或者文件保护 2、系统安装了一个或者多个流氓软件,这出现IE 或者系统崩溃的机会也比较大,也有可能出现文件保护 3、系统加载的程序或者系统正在运行的程序之前有冲突,尤其是部分杀毒软件监控程序 4、系统本身存在漏洞,导致容易受到网络攻击。 5、病毒问题也是主要导致内存不能为Read、文件保护、Explorer.exe 错误…… 6、如果在玩游戏时候出现内存不能为Read,则很大可能是显卡驱动不适合(这里的不适合有不适合该游戏、不适合电脑的显卡),也有可能是DX9.0C 版本不够新或者不符合该游戏、显卡驱动 7、部分软件本身自身不足的问题 8、电脑硬件过热,也是导致内存不能为Read 的原因之一。 9、电脑内存与主板兼容性不好也是导致内存不能为Read 的致命原因! 希望以上总结能够对大家判断导致内存不能为Read 问题的原因有帮助。 分析: 一般来说,电脑硬件是很不容易坏的。内存出现问题的可能性并不大(除非你的内存真的是杂牌的一塌徒地),主要方面是:1。内存条坏了(二手内存情况居 多)、2。使用了有质量问题的内存,3。内存插在主板上的金手指部分灰尘太多。4。使用不同品牌不同容量的内存,从而出现不兼容的情况。5。超频带来的散 热问题。你可以使用MemT est 这个软件来检测一下内存,它可以彻底的检测出内存的稳定度。 二、如果都没有,那就从软件方面排除故障了。 先说原理:内存有个存放数据的地方叫缓冲区,当程序把数据放在缓冲区,需要操作系统提供的“功能函数”来申请,如果内存分配成功,函数就会将所新开辟的内 存区地址返回给应用程序,应用程序就可以通过这个地址使用这块内存。这就是“动态内存分配”,内存地址也就是编程中的“光标”。内存不是永远都招之即来、 用之不尽的,有时候内存分配也会失败。当分配失败时系统函数会返回一个0值,这时返回值“0”已不表示新启用的光标,而是系统向应用程序发出的一个通知, 告知出现了错误。作为应用程序,在每一次申请内存后都应该检查返回值是否为0,如果是,则意味着出现了故障,应该采取一些措施挽救,这就增强了程序的“健 壮性”。若应用程序没有检查这个错误,它就会按照“思维惯性”认为这个值是给它分配的可用光标,继续在之后的执行中使用这块内存。真正的0地址内存区储存 的是计算机系统中最重要的“中断描述符表”,绝对不允许应用程序使用。在没有保护机制的操作系统下(如DOS),写数据到这个地址会导致立即当机,而在健 壮的操作系统中,如Windows等,这个操作会马上被系统的保护机制捕获,其结果就是由操作系统强行关闭出错的应用程序,以防止其错误扩大。这时候,就

最新整理Intel处理器命名规则是怎样的

I n t e l处理器命名规则是怎样的 相信我们大多数人电脑都是使用I n t e l的处理器,处理器有很多种,官方都是怎么进行命名的呢?在I n t e l C P U型号中,都有哪些C P U是带后缀的呢?请看下文解析。 I n t e l处理器命名规则是怎样的? M:笔记本专用C P U,一般为双核,M前面一位数字是0,意味着是标准电压处理器,如果是7,则是低电 压处理器。 U:笔记本专用低电压C P U,一般为双核,U前面一位数字为8,则是28W功耗的低压处理器(标准电压双核处理器功耗为35W),若前一位数字为7,则是17W功耗的低压处理器,若为0,则是15W功耗的低压处理器。 H:是高电压的,是焊接的,不能拆卸。 X:代表高性能,可拆卸的。 Q:代表至高性能级别。 Y:代表超低电压的,除了省电,没别的优点的了,是不能拆卸的。 T:是涡轮增压技术,能增加C P U的转速,比如5400转的,可以提升到7200转,用来增加C P U性能。 K:可以超频的版本。

无后缀的是标准版。 Q M(第四代开始改为M Q):笔记本专用C P U,Q是Q u a d 的缩写,即四核C P U。若Q M前一位数字是0,则表示此产品为功耗45W的标准电压四核处理器,若为2,则表示此产品为35W功耗的低电压四核处理器,若为5,与对应为0的C P U主要规格相同,但集成的核芯显卡频率更高(如3630Q M和3635Q M,后者核显最大频率 1.2G H z,前者则是 1.15G H z)。 H Q:第四代C P U新出现的系列,主要参数和标准的四核C P U一致,但集成了性能空前强大的核芯显卡I r i s P r o5200系列,这种核显的性能可以直接媲美中端独立显卡。目前有i74750H Q,4850H Q和4950H Q三款C P U,后来出了一款i7 4702H Q,并没有集成高性能核芯显卡,是定位较为模糊的一款产品。 X M:最强大的笔记本C P U,功耗一般为55W。X意为E x t r e m e,此类型C P U完全不锁频,在散热和供电允许 的情况下可以无限制超频,而即便是默认频率下,也比同一时代的其它产品强大得多。这类C P U都是工厂生产后精心挑选出来得极品,质量极佳,性能完美,但价格非常昂贵。一块X M系列的C P U批发价可达1000美金以

内存字节对齐

1.内存字节对齐和小端模式: /* 本程序是关于:编译器内存的字节对齐方式和存储时的小端对齐模式(win7 32bit) #pragma pack(n) 默认为8字节对齐,(即n=8)其中n的取值为1,2,4,8,16,32等 内存字节对齐大小和方式: 1)结构体内变量对齐: 每个变量的对齐字节数大小argAlignsize=min(#pragma pack(n),sizeof(变量)); 方式:结构体的第一个变量的初始偏移地址为0,其它变量的偏移地址(当前变量的起始地址)必须是argAlignsize的整数倍,不够整数倍的补空,不添加任何数据 2)结构体对齐: 结构体的对齐字节数大小strAlignsize=min(#pragma pack(n),sizeof(所有变量中最大字节的变量)) 方式: A.对于单独的结构体来说,结构体本身按照strAlignsize大小来对齐 B.结构体B在结构体A中时,结构体B的起始地址是结构体B的 strAlignsize大小的整数倍 小端对齐模式: 指针指着一个存储空间,存储空间地址由低到高的存储内容为:0x78,0x67,0x33,0x45 若指针为char,则获取的数据为0x78 若指针为short,则获取的数据为0x6778 若指针为long,则获取的数据为0x45336778 */ #include using namespace std; /*更改C编译器内存的缺省字节对齐方式,由默认的n=4字节,变为n字节对齐,其中n的取值为1,2,4,8,16,32等*/ #pragma pack(2) struct A { unsigned char a; unsigned short b; }; struct B { unsigned char c; unsigned int d;

寄存器sse2指令集

sse2指令集 1移动指令: 1. Movaps movaps XMM,XMM/m128 movaps XMM/128,XMM 把源存储器内容值送入目的寄存器,当有m128时,必须对齐内存16字节,也就是内存地址低4位为0. 2. Movups movups XMM,XMM/m128 movaps XMM/128,XMM 把源存储器内容值送入目的寄存器,但不必对齐内存16字节 3. Movlps movlps XMM,m64 把源存储器64位内容送入目的寄存器低64位,高64位不变,内存变量不必对齐内存16字节4. Movhps movhps XMM,m64 把源存储器64位内容送入目的寄存器高64位,低64位不变,内存变量不必对齐内存16字节. 5. Movhlps movhlps XMM,XMM 把源寄存器高64位送入目的寄存器低64位,高64位不变. 6. Movlhps movlhps XMM,XMM 把源寄存器低64位送入目的寄存器高64位,低64位不变. 7. movss movss XMM,m32/XMM 原操作数为m32时:dest[31-00] <== m32 dest[127-32] <== 0 原操作数为XMM时: dest[31-00] <== src[31-00] dest[127-32]不变 8. movmskpd movmskpd r32,XMM 取64位操作数符号位 r32[0] <== XMM[63] r32[1] <== XMM[127] r32[31-2] <== 0

9. movmskps movmskps r32,XMM 取32位操作数符号位 r32[0] <== XMM[31] r32[1] <== XMM[63] r32[2] <== XMM[95] r32[3] <== XMM[127] r32[31-4] <== 0 10. pmovmskb pmovmskb r32,XMM 取16位操作数符号位具体操作同前 r[0] <== XMM[7] r[1] <== XMM[15] r[2] <== XMM[23] r[3] <== XMM[31] r[4] <== XMM[39] r[5] <== XMM[47] r[6] <== XMM[55] r[7] <== XMM[63] r[8] <== XMM[71] r[9] <== XMM[79] r[10] <== XMM[87] r[11] <== XMM[95] r[12] <== XMM[103] r[13] <== XMM[111] r[14] <== XMM[119] r[15] <== XMM[127] r[31-16] <== 0 11. movntps movntps m128,XMM m128 <== XMM 直接把XMM中的值送入m128,不经过cache,必须对齐16字节. 12. Movntpd movntpd m128,XMM m128 <== XMM 直接把XMM中的值送入m128,不经过cache,必须对齐16字节. 13. Movnti movnti m32,r32 m32 <== r32 把32寄存器的值送入m32,不经过cache. 14. Movapd movapd XMM,XMM/m128 movapd XMM/m128,XMM 把源存储器内容值送入目的寄存器,当有m128时,必须对齐内存16字节 15. Movupd movupd XMM,XMM/m128 movapd XMM/m128,XMM 把源存储器内容值送入目的寄存器,但不必对齐内存16字节. 我感觉这两条指令同movaps 和movups 指令一样,不过又不确定. 16. Movlpd movlpd XMM,m64 movlpd m64,XMM 把源存储器64位内容送入目的寄存器低64位,高64位不变,内存变量不必对齐内存16字节

操作系统内存管理原理

内存分段和请求式分页 在深入i386架构的技术细节之前,让我们先返回1978年,那一年Intel 发布了PC处理器之母:8086。我想将讨论限制到这个有重大意义的里程碑上。如果你打算知道更多,阅读Robert L.的80486程序员参考(Hummel 1992)将是一个很棒的开始。现在看来这有些过时了,因为它没有涵盖Pentium处理器家族的新特性;不过,该参考手册中仍保留了大量i386架构的基本信息。尽管8086能够访问1MB RAM的地址空间,但应用程序还是无法“看到”整个的物理地址空间,这是因为CPU寄存器的地址仅有16位。这就意味着应用程序可访问的连续线性地址空间仅有64KB,但是通过16位段寄存器的帮助,这个64KB大小的内存窗口就可以在整个物理空间中上下移动,64KB逻辑空间中的线性地址作为偏移量和基地址(由16位的段寄存器给处)相加,从而构成有效的20位地址。这种古老的内存模型仍然被最新的Pentium CPU支持,它被称为:实地址模式,通常叫做:实模式。 80286 CPU引入了另一种模式,称为:受保护的虚拟地址模式,或者简单的称之为:保护模式。该模式提供的内存模型中使用的物理地址不再是简单的将线性地址和段基址相加。为了保持与8086和80186的向后兼容,80286仍然使用段寄存器,但是在切换到保护模式后,它们将不再包含物理段的地址。替代的是,它们提供了一个选择器(selector),该选择器由一个描述符表的索引构成。描述符表中的每一项都定义了一个24位的物理基址,允许访问16MB RAM,在当时这是一个很不可思议的数量。不过,80286仍然是16位CPU,因此线性地址空间仍然被限制在64KB。 1985年的80386 CPU突破了这一限制。该芯片最终砍断了16位寻址的锁链,将线性地址空间推到了4GB,并在引入32位线性地址的同时保留了基本的选择器/描述符架构。幸运的是,80286的描述符结构中还有一些剩余的位可以拿来使用。从16位迁移到32位地址后,CPU的数据寄存器的大小也相应的增加了两倍,并同时增加了一个新的强大的寻址模型。真正的32位的数据和地址为程序员带了实际的便利。事实上,在微软的Windows平台真正完全支持32位模型是在好几年之后。Windows NT的第一个版本在1993年7月26日发布,实现了真正意义上的Win32 API。但是Windows 3.x程序员仍然要处理由独立的代码和数据段构成的64KB内存片,Windows NT提供了平坦的4GB地址空间,在那儿可以使用简单的32位指针来寻址所有的代码和数据,而不需要分段。在内部,当然,分段仍然在起作用,就像我在前面提及的那样。不过管理段的所有责任都被移给了操作系统。

主流显卡命名规则

1楼 在Nvidia的显卡中。GT表示的是加强版的意思。8800GT就是8800的加强版。不过GTS是加加强版,所以8800GTS是比8800GT强的。还有就是Ultra是加加加强版的意思。说白了就是文字游戏,Nvidia现在的显卡最低也是GT,全是加强版,没意思。 显卡后缀解释: 1、NVIDIA方面: Ultra:NV暂时的顶级型号,以前认为和GTX一个等级,自从8800U出来以后就不同啦,比GTX更强!!Ultra现在可以认为是GTX的官方超频板,Best!! GTX:暂时比Ultra低端一些,以前的旗舰型号,但绝对是不容小时的... GTS:新兴的显卡型号,起初出现于G80系列,定位约等于ATI的XT,定位比T更高,代表作有8600GTS和8800GTS... GT:高级版,现在定位比GTS低一些,主要在于PCB、核心频率和显存规格,以前是中段产品的最高级版,代表作8600GT... GS:Nv系列中中段偏上的显卡型号,比GT还要低,但是在G80系列中已不见踪影,代表作7600GS和7300GS.. LE:最差的一种,缩水版,一般不推荐购买:7300LE最为经典... 2、ATI方面: XTX:最高的等级,只限于旗舰产品!如1900XTX和1950XTX... XT:频率比XTX稍低一点的型号,但也代表着中低端的最高型号,如1650XT、1950XT... GT/PRO:大概就是高级般的意思,“PRO”在英语中就是“高能”的意思,地位比XT稍低,最典型的就是1650GT和2600pro... 总结:还是ATI的型号简洁,不像Nvidia一样一个系列变一次。 2楼 ATi显卡命名规律 和nVIDIA一样,ATi显卡的命名也按照了一定的规律进行,对相同核心的不同型号显卡,以不同的命名规则区分开,以方便消费群体识别好显卡之间的级别,下面我们就说说ATi 常见的命名规律。 XTX > XT > XL/GTO > Pro/GT > SE XTX:ATI系列中最高端显卡型号的后缀,如:1800XTX,1900XTX。这个后缀编号都是当时最高端的ATi显卡所配有的。 XT:这个编号比较有意思,ATi和nVIDIA都采用这个编号,但两者表达的意义却不同,用户需要区分开。 在ATi方面,XT是代表了顶级显卡的型号,一般就运行频率稍低于XTX,XT与XTX的关系就像nVIDIA中GTX和Ultra的一样。我们知道的高端显卡就有Radeon X1950XT、 Radeon HD 2900XT,它们都采用了XT这个后缀。 而在nVIDIA方面,XT却是代表了简化版,比标准版更低,如GeForce 5600XT,消费者需要区分开来。但在以后的代数中,nVIDIA也很少用到XT这个后缀命名。 XL:用于ATi高端显卡系列的后缀,级别比顶级级别的XT低,主要表现在频率和管线上有所缩水。 GTO:是ATi较为特殊的命名后缀,也是用于中高端显卡系列,其意义就有点类似于nVIDIA 的“GS”一样,比XL级别稍低。

内存对齐

C语言内存对齐 分类:C/C++2012-04-05 20:54 1070人阅读评论(1) 收藏举报语言c编译器平台oo 首先由一个程序引入话题: 1//环境:vc6 + windows sp2 2//程序1 3 #include 4 5using namespace std; 6 7struct st1 8 { 9char a ; 10int b ; 11short c ; 12 }; 13 14struct st2 15 { 16short c ; 17char a ; 18int b ; 19 }; 20 21int main() 22 { 23 cout<<"sizeof(st1) is "<

程序的输出结果为: sizeof(st1) is 12 sizeof(st2) is 8 问题出来了,这两个一样的结构体,为什么sizeof的时候大小不一样呢? 本文的主要目的就是解释明白这一问题。 内存对齐,正是因为内存对齐的影响,导致结果不同。 对于大多数的程序员来说,内存对齐基本上是透明的,这是编译器该干的活,编译器为程序中的每个数据单元安排在合适的位置上,从而导致了相同的变量,不同声明顺序的结构体大小的不同。 那么编译器为什么要进行内存对齐呢?程序1中结构体按常理来理解sizeof(st1)和sizeof(st2)结果都应该是7,4(int) + 2(short) + 1(char) = 7 。经过内存对齐后,结构体的空间反而增大了。 在解释内存对齐的作用前,先来看下内存对齐的规则: 1、对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。 2、在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。 #pragma pack(n) 表示设置为n字节对齐。VC6默认8字节对齐 以程序1为例解释对齐的规则:

C语言内存字节对齐规则20180718

C语言内存字节对齐规则 在C语言面试和考试中经常会遇到内存字节对齐的问题。今天就来对字节对齐的知识进行小结一下。 首先说说为什么要对齐。为了提高效率,计算机从内存中取数据是按照一个固定长度的。以32位机为例,它每次取32个位,也就是4个字节(每字节8个位,计算机基础知识,别说不知道)。字节对齐有什么好处?以int型数据为例,如果它在内存中存放的位置按4字节对齐,也就是说1个int的数据全部落在计算机一次取数的区间内,那么只需要取一次就可以了。如图a-1。如果不对齐,很不巧,这个int数据刚好跨越了取数的边界,这样就需要取两次才能把这个int的数据全部取到,这样效率也就降低了。 图:a-1 图:a-2 内存对齐是会浪费一些空间的。但是这种空间上得浪费却可以减少取数的时间。这是典型的一种以空间换时间的做法。空间与时间孰优孰略这个每个人都有自己的看法,但是C 语言既然采取了这种以空间换时间的策略,就必然有它的道理。况且,在存储器越来越便宜的今天,这一点点的空间上的浪费就不算什么了。 需要说明的是,字节对齐不同的编译器可能会采用不同的优化策略,以下以GCC为例讲解结构体的对齐. 一、原则: 1.结构体内成员按自身按自身长度自对齐。

自身长度,如char=1,short=2,int=4,double=8,。所谓自对齐,指的是该成员的起始位置的内存地址必须是它自身长度的整数倍。如int只能以0,4,8这类的地址开始 2.结构体的总大小为结构体的有效对齐值的整数倍 结构体的有效对齐值的确定: 1)当未明确指定时,以结构体中最长的成员的长度为其有效值 2)当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值。 3)当用__attribute__ ((__packed__))指定长度时,强制按照此值为结构体的有效对齐值 二、例子 1) struct AA{ //结构体的有效对齐值为其中最大的成员即int的长度4 char a; int b; char c; }aa 结果,sizeof(aa)=12 何解?首先假设结构体内存起始地址为0,那么地址的分布如下 0 a 1 2 3 4 b 5 b 6 b 7 b 8 c 9 10 11 char的字对齐长度为1,所以可以在任何地址开始,但是,int自对齐长度为4,必须以4的倍数地址开始。所以,尽管1-3空着,但b也只能从4开始。再加上c后,整个结构体的总长度为9,结构体的有效对齐值为其中最大的成员即int的长度4,所以,结构体的大小向上扩展到12,即9-11的地址空着。 2) //结构体的有效对齐值为其中最大的成员即int的长度4 struct AA{ char a; char c; int b; }aa sizeof(aa)=8,为什么呢 0 a 1 c

windows操作系统内存管理方式综述

一页式管理 1 页式管理的基本原理将各进程的虚拟空间划分成若干个长度相等的页(page),页式管理把内存空间按页的大小划分成片或者页面(page frame),然后把页式虚拟地址与内存地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。 它分为 1 静态页式管理。静态分页管理的第一步是为要求内存的作业或进程分配足够的页面。系统通过存储页面表、请求表以及页表来完成内存的分配工作。静态页式管理解决了分区管理时的碎片问题。但是,由于静态页式管理要求进程或作业在执行前全部装入内存,如果可用页面数小于用户要求时,该作业或进程只好等待。而且作业和进程的大小仍受内存可用页面数的限制。 2 动态页式管理。动态页式管理是在静态页式管理的基础上发展起来的。它分为请求页式管理和预调入页式管理。 优点:没有外碎片,每个内碎片不超过页大小。一个程序不必连续存放。便于改变程序占用空间的大小(主要指随着程序运行而动态生成的数据增多,要求地址空间相应增长,通常由系统调用完成而不是操作系统自动完成)。 缺点:程序全部装入内存。 要求有相应的硬件支持。例如地址变换机构,缺页中断的产生和选择淘汰页面等都要求有相应的硬件支持。这增加了机器成本。增加了系统开销,例如缺页中断处理机,请求调页的算法如选择不当,有可能产生抖动现象。虽然消除了碎片,但每个作业或进程的最后一页内总有一部分空间得不到利用果页面较大,则这一部分的损失仍然较大。 二段式管理的基本思想 把程序按内容或过程(函数)关系分成段,每段有自己的名字。一个用户作业或进程所包含的段对应一个二维线形虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址影射机构把段式虚拟地址转换为实际内存物理地址。 程序通过分段(segmentation)划分为多个模块,如代码段、数据段、共享段。其优点是:可以分别编写和编译。可以针对不同类型的段采取不同的保护。可以按段为单位来进行共享,包括通过动态链接进行代码共享。 三段页式管理的实现原理 1 虚地址的构成 一个进程中所包含的具有独立逻辑功能的程序或数据仍被划分为段,并有各自的段号s。这反映相继承了段式管理的特征。其次,对于段s中的程序或数据,则按照一定的大小将其划分为不同的页。和页式系统一样,最后不足一页的部分仍占一页。这反映了段页式管理中的页式特征。从而,段页式管理时的进程的虚拟地址空间中的虚拟地址由三部分组成:即段号s,页号P和页内相对地址d。虚拟空间的最小单位是页而不是段,从而内存可用区也就被划分成为着干个大小相等的页面,且每段所拥有的程序和数据在内存中可以分开存放。分段的大小也不再受内存可用区的限制。 2 段表和页表

显卡命名规则

显卡命名规则 蓝宝石、华硕、迪兰恒进、丽台、XFX讯景、技嘉、映众、微星、艾尔莎、富士康、捷波、磐正、映泰、耕升、旌宇、影驰、铭瑄、翔升、盈通、祺祥、七彩虹、斯巴达克、索泰、双敏、精英、昂达 英伟达(nvidia)命名规则: 一般的版本有GTX 、GTS 、GT 、GS排序是GTX >GTS >GT >GS GS (入门级)普通版或GT的简化版。 GT (主流级)常见的游戏芯片。比GS高一个档次,因为GT没有缩减管线和顶点单元。 GTS(性能级)介于GT和GTX之间的版本GT的加强版 GTX (GT eXtreme 旗舰级)代表着最强的版本简化后成为成为GT 版本级别: 除了上述标准版本之外,还有些特殊版,特殊版一般会在标准版的型号后面加个后缀,常见的有: GE 也是简化版不过略微强于GS一点点,影驰显卡用来表示"骨灰玩家版"的东东 ZT 在XT基础上再次降频以降低价格。 XT 降频版,而在A Ti中表示最高端。 LE (Lower Edition 低端版) 和XT基本一样,A Ti也用过。 SE 和LE相似基本是GS的简化版最低端的几个型号 MX 平价版,大众类,如著名的MX440 Ultra 在GF8系列之前代表着最高端,但9系列最高端的命名就改为GTX 。 GT2 eXtreme 双GPU显卡。 TI (Titanium 钛)以前的用法一般就是代表了nVidia的高端版本。 Go 用于移动平台。 TC (Turbo Cache)可以占用内存的显卡 GX2(GT eXtreme2)指两块显卡以SLI并组的方式整合为一块显卡,不同于SLI的是只有一个接口。如9800GX2 7950GX2 自G100系列之后,NVIDIA重新命名显卡后缀版本,使产品线更加整齐 GTX高端/性能级显卡GTX295 GTX275 GTX285 GTX280 GTX260 GT代表主流产品线GT120 GT130 GT140 GTS250(9500GT 9600GT 9800GT 9800GTX+ ) G低端入门产品G100 G110 (9300GS 9400GT ) AMD(A TI)的命名规则: A TI显卡是按一定的规则命名的,对于相同核心不同型号的显卡,以不同的命名规则命名,

C语言内存对齐

解析C语言结构体对齐(内存对齐问题) C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。内容虽然很基础,但一不小心就会弄错。写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久。其实相关的文章很多,感觉说清楚的不多。结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。) 原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。 这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。 例1:struct { short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; sizeof(A) = 6; 这个很好理解,三个short都为2。 sizeof(B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。 例2:struct A{ int a; char b; short c; }; struct B{ char b; int a; short c; }; sizeof(A) = 8; int为4,char为1,short为2,这里用到了原则1和原则3。 sizeof(B) = 12; 是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则1和原则3。

现代内存颗粒编码细则

现代(Hynix)内存编号示含义 (2010-01-21 17:04:43) 转载▼ 标签: 分类:电脑知识 电脑 ddr400 hynix ddr内存 it HY5DU56822AT-H 现代内存编号示意图 A部分标明的是生产此颗粒企业的名称——Hynix。 B部分标明的是该内存模组的生产日期,以三个阿拉伯数字的形式表现。第一个阿拉伯数字表示生产的年份,后面两位数字表明是在该年的第XX周生产出来的。如上图中的517表示该模组是在05年的第17周生产的 C部分表示该内存颗粒的频率、延迟参数。由1-3位字母和数字共同组成。其根据频率、延迟参数不同,分别可以用“D5、D43、D4、J、M、K、H、L”8个字母/数字组合来表示。其含义分别为D5代表DDR500(250MHz),延迟为3-4-4;D43代表DDR433(216MHz),延迟为3-3-3;D4代表DDR400(200MHz),延迟为3-4-4;J代表DDR333(166MHz),延迟为2.5-3-3;M代表DDR266(133MHz),延迟为2-2-2;K代表DDR266A(133MHz),延迟为2-3-3;H代表DDR266B(133MHz),延迟为2.5-3-3;L代表DDR200(100MHz),延迟为2-2-2。 D部分编号实际上是由12个小部分组成,分别表示内存模组的容量、颗粒的位宽、工作电压等信息。具体详细内容如图二

所示D部分编号12个小部分分解示意图采用现代颗粒的内存颗粒特写 第1部分代表该颗粒的生产企业。“HY”是HYNIX的简称,代表着该颗粒是现代生产制造。第2部分代表产品家族,由两位数字或字母组成,“5D”表示为DDR内存,“57”表示为SDRAM内存第3部分代表工作电压,由一个字母组成。其中含义为V代表VDD=3.3V & VDDQ=2.5V; U代表VDD=2.5V & VDDQ=2.5V;W代表VDD=2.5V & VDDQ=1.8V;S代表VDD=1.8V & VDDQ=1.8V 来分别代表不同的工作电压 第4部分代表内存模组的容量和刷新设置,由两位数字或字母组成。对于DDR 内存,分别由“64、66、28、56、57、12、1G”来代表不同的容量和刷新设置。其中含义为:64代表64MB容量,4K刷新;66代表64MB容量,2K刷新; 28代表128MB容量,4K刷新;56代表256MB容量,8K刷新;57代表256MB容量,4K 刷新;12代表512MB容量,8K刷新;1G代表1GB容量,8K刷新 第5部分代表该内存颗粒的位宽,由1个或2个数字组成。分为4种情况,分别用“4、8、16、32”来分别代表4bit、8bit、16bit和32bit 第6部分表示的是Bank数,由1个数字组成。有三种情况,分别是“1”代表2 bank,“2”代表4 bank,“4”代表8 bank 第7部分代表接口类型,由一个数字组成。分为三种情况,分别是“1”代表SSTL_3,“2”代表SSTL_2;“3”代表SSTL_18 第8部分代表该颗粒的版本,由一个字母组成,这部分的字母在26个字母中的位置越*后,说明该内存颗粒的版本越新,目前为止HY内存共有5个版本,表现在编号上,空白表示第一版,“A”表示第二版,依次类推,到第5版则有“D”来代表。购买内存的时候版本越说明新电器性能越好 第9部分代表的是功耗,如果该部分是空白,则说明该颗粒的功耗为普通,如果该部分出现了“L”字母,则代表该内存颗粒为低功耗 第10部分代表内存的封装类型,由一个或两个字母组成。由“T”代表TOSP 封装,“Q”代表LOFP封装,“F”代表FBGA封装,“FC”代表FBGA(UTC:8 x 13mm)封装 第11部分代表堆叠封装,由一个或两个字母组成。空白代表普通;S代表

C语言结构体对齐

C语言结构体对齐 C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。内容虽然很基础,但一不小心就会弄错。写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久。其实相关的文章很多,感觉说清楚的不多。结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b 里有char,int,double等元素,那b应该从8的整数倍开始存储。) 原则3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。 这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。 例1:struct { short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; sizeof(A) = 6; 这个很好理解,三个short都为2。 sizeof(B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,

Win7内存占用高—怎么节省电脑Win7系统内存

Win7内存占用高—怎么节省电脑Win7系统内存 Win7系统在启动的过程中会启动许多服务,它们会占用一部分系统资源,事实上,有些服务大家根本不需要使用,因此,管理员可以关闭多余的服务,以节省内存。 节省Win7系统资源内存的办法: 1:单击按钮,在搜索框输入“服务”,然后在“程序”列表中选择“服 务”选项。 2:打开服务窗口后,双击要停用的服务。 3:打开“属性”对话框后,在“常规”选项卡中的“描述”区域查看该服务的作用,然后打开“依存关系”选项卡,查看该服务与其他服务的依存关系,如图1-1所示: 图1-1 在确定该服务不需使用而且停用后不会影响系统正常运行的情况下,在“常规”选项卡下禁用该服务。如图1-2所示:

图1-2 关于各项服务的功能,在服务的“描述”区域中有简单说明,此外,也可以通过互联网查找相关的资料。下面列举几个普通不常用的服务: 1:Adaptive brightness:监视氛围光传感器,以检测氛围光的变化并调节显示器的亮度。停止或禁用此服务后,显示器亮度将不根据照明条件进行调节。该服务的默认运行方式是手动,如果没有使用触摸屏这一类智能调节屏幕亮度的设备,就可以放心禁用该功能。 2:Bluetooth Support Service:蓝牙功能支持,如果电脑不连接蓝牙设备,可以停用该服务。 3:Certificate Propagation:智能卡证书支持,对于未配置智能卡的电脑而言,该服务没有任何作用。 4:Print Spooler:这项服务主要为打印功能提供支持,如果电脑没有安装打印机并且不需要使用虚拟打印功能,可关闭该服务。 更多WIN7系统下载敬请关注windows7之家

相关文档
最新文档