ARM 内存对齐总结

发布者:DelightfulGaze最新更新时间:2016-03-31 来源: eefocus关键字:ARM  内存对齐 手机看文章 扫描二维码
随时随地手机看文章
一、啥是内存对齐?为啥要内存对齐?

      现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问都可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就是对齐。
字节对齐的原因大致是如下两条:
      1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
      2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

二、对齐规则
       每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。规则:
       1. 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在偏移量为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行,

即各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的整数倍。
       2. 结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
       3. 结合1、2可推断:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

三、X86对齐实验
       下面再简要回顾解释一下上述的对齐规则,结合实例进行分析:
       1. 数据类型自身的对齐值:对于char型数据,其自身对齐值为1字节,对于short型为2字节,对于

int,float,double类型,其自身对齐值为4字节。
       2. 结构体的自身对齐值:其成员中自身对齐值最大的那个值。
       3. 指定对齐值: #pragma   pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始

地址的偏移量有两种情况,第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
       4. 数据成员和结构体的有效对齐值:数据成员(数据类型)和数据结构的自身对齐值和指定对齐值中小的那个值,数据成员对齐了数据结构自然也就对齐了。
      了解上述四个基本概念,我们开始讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值。有效对齐N,就是表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0"。而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍)。下面结合VS2005中编译环境的例子进行深入了解:
例子B分析:
struct B
{
char b;
int a;
short c;
};
假设B从地址空间0x0000开始排放。该例中没有显式指定对齐值N,VS2005默认值为4。
    成员变量b自身对齐值是1,比指定或默认指定对齐值4小,故有效对齐值为1,其存放地址0x0000符合0x0000%1=0,满足字节对齐原则。
    成员变量a自身对齐值为4,和指定或默认指定对齐值4相等,故有效对齐值也为4,为了保证字节对齐,成员变量a只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0。
    成员变量c自身对齐值为2,比指定或默认指定对齐值4小,故有效对齐值为2,可顺序存放在0x0008至0x0009两个字节空间中,符合0x0008%2=0。
    至此满足了数据成员的字节对齐,接着看数据结构B的对齐。数据结构B的自身对齐值为其变量中最大对齐值(也就是成员变量b)4,故结构体B的有效对齐值也是4。根据结构体圆整的要求, 0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B 共有12个字节,sizeof(struct B)=12。
    之所以在变量C补充2字节,是因为要实现编译器快速有效的存取结构数组,试想如果定义B结构数组,第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果不把结构的大小补充为对齐值(4)的整数倍,那下一个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了。
例子C分析:

__align(2) struct C
{
char b;
int a;
short c;
};
   同理,例子C中成员变量b自身对齐值为1,指定对齐值为2,故效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x0000%1= 0,满足字节对齐原则。
   成员变量a自身对齐值为4,指定对齐值为2,故有效对齐值为2,顺序存放在0x0002、0x0003、0x0004、0x0005四个连续字节中,符合0x0002%2=0,满足字节对齐原则。
   成员变量c的自身对齐值为2,与指定对齐值相等,故有效对齐值为2,顺序存放在0x0006、0x0007中,符合 0x0006%2=0,满足字节对齐原则。
   从0x0000到0x00007共八字节存放的是结构体C的变量。结构体C自身对齐值为4,比指定对齐值2大,故C的有效对齐值为2,因8%2=0,C只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8,完全满足字节对齐原则。除了指定的对齐值不同能导致数据结构的地址存放不同外, 编译器不同存放结构体方式也可能不同。

四、ARM平台的对齐问题
    在ARM中,有ARM和Thumb两种指令。
    ARM指令:每执行一条指令,PC的值加4个字节(32bits).一次访问4字节内容,该字节的起始地址必须是4字节对齐的位置上,即地址的低两位为bits[0b00],也就是说地址必须是4的倍数。
    Thumb指令:每执行一条指令,PC的值加2个字节(16bits).).一次访问2字节内容,该字节的起始地址必须是2字节对齐的位置上,即地址的低两位为bits[0b0],也就是说地址必须是2的倍数。
     遵循以上方式叫对齐(aligned)方式,不遵守这样方式称为非对齐(unaligned)的存储访问操作。

五、ARM平台字节对齐关键字
  1. __align(num)用于修改最高级别对象的字节边界。
    A、在汇编中使用LDRD或者STRD时,就用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。
    B、该修饰对象的命令最大是8个字节限制,可让2字节的对象按4字节对齐,但不能让4字节的对象2字节对齐。
    C、 __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。   
  2. __packed 是进行一字节对齐。
    A、不能对packed的对象进行对齐;
    B、所有对象的读写访问都进行非对齐访问;
    C、float及包含float的结构联合及未用__packed的对象将不能字节对齐;
    D、__packed对局部整形变量无影响;
    E、强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定义为:

       packed __packed int* p; //__packed int 则没有意义。

  3. __unaligned   用于修饰该变量可按照非对齐访问。

六、如何查找与字节对齐方面的问题,如果出现对齐或者赋值问题首先查看:
  1. 编译器的big little端设置;
  2. 看这种体系本身是否支持非对齐访问;
  3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。

七、结论
   针对于32位处理器对于本地使用的数据结构,为提高内存访问效率,采用四字节对齐方式;同时为了减少内存的开销,合理安排结构成员的位置,减少四字节对齐导致的成员之间的空隙,降低内存开销。
   对于处理器之间的数据结构,需要保证消息的长度不因为在不同编译平台和不同处理器导致消息结构的长度发生变化,使用一字节对齐方式对消息结构进行紧缩;为保证处理器之间的消息的数据结构的内存访问效率,采用字节填充的方式自己对消息中成员进行四字节对齐。
   数据结构的成员位置要兼顾成员之间的关系、数据访问效率和空间利用率。顺序安排的原则是:四字节的放在最前面,两字节的紧接最后一个四字节成员,一字节紧接最后一个两字节成员,填充字节放在最后。举例如下:
typedef struct tag_T_MSG{
long ParaA;
long ParaB;
short ParaC;
char ParaD;
char Pad;
} T_MSG;


关键字:ARM  内存对齐 引用地址:ARM 内存对齐总结

上一篇:ARM根文件系统制作
下一篇:很好的 ARM指令集解析

推荐阅读最新更新时间:2024-03-16 14:48

获得中移动万台采购大单,ARM服务器进入爆发前夜?
近日,中国移动发布集中网络云资源池三期工程计算型服务器采购招标公告,ARM平台的需求数量为14710台,采购规模与采购金额均超过总量的三分之一。 据悉,这也是中国移动在网络云集采中首次明确ARM平台的采购数量与比例。对于想进入服务器领域ARM架构来说,这是一个重大利好。 自上而下的突破 据IDC数据统计,2020年ARM架构的服务器销售额大幅增长430.5%。即便基数很小,这也是一个惊人的成绩。 稍微了解ARM历史的人都知道,从2008年开始,ARM就立志上攻服务器市场。但诸多条件的不顺,使得AMD、博通、Cavium、高通、英伟达、三星等一众芯片盟友都无功而返。 局面的打破最终来自于系统厂商。出于成本和可控性的考量,云计
[手机便携]
获得中移动万台采购大单,<font color='red'>ARM</font>服务器进入爆发前夜?
ARM的两种启动方式 (NAND FLASH. NOR FLASH)
为什么会有两种启动方式? 这就是有两种FLASH 的不同特点决定的。 NAND FLASH 容量大,存储的单位比特数据的成本要低很多,但是要按照特定的时序对NAND FLASH 进行读写,因此CPU 无法对NAND FLASH 的数据进行直接寻址,CPU 对NAND FLASH 中数据的读写是通过专门的 nand flash控制器进行的,因此 NAND FLASH 更适合于存储数据。 NOR FLASH 容量小,速度快,对NOR FLASH 进行读写时,输入地址,然后给出读写信号即可从数据总线上得到数据,但是价格要比NAND FLASH 高因此适合做程序存储器。 综上所述,NOR FLASH 可以直接连接到arm 的
[单片机]
ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称 this whole ARM thing is a f*cking pain in the ass ,引发ARM Linux社区的地震,随后ARM社区进行了一系列的重大修正。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的plat
[单片机]
嵌入式linux开发 (十八) 内存管理(2) ARM内存管理
硬件对内存的管理 armv7v8 ARM是统一编址的,也就是外设和(内存A)进行统一的编址,共同形成了4G物理地址空间(32位为例子)。 内存控制器属于外设,内存属于(内存A). 一个soc内部及外扩的内存都属于(内存A). 存储器架构 哈佛架构 cortex-M cortex-A MPU MMU 的概念定义及实现定义 MPU: The memory protection unit (MPU) is used to manage the CPU accesses to memory to prevent one task to accidentally corrupt the memory or resources
[单片机]
基于嵌入式ARM的LCD图像显示系统设计
0 引 言 随着嵌入式技术迅猛发展和Linux在信息行业中广泛应用,利用嵌入式Linux系统实现图像采集处理已有可能。实时获得图像数据是实现这些应用的重要环节。本文使用的系统硬件平台采用Samsung公司的处理器S3C2410,并以此为基础,在基于嵌入式Linux系统平台上设计了建立图像视频的一种方法。 1 系统硬件电路设计 S3C2410芯片处理器内部集成了ARM公司ARM920T处理器核的32位微控制器,资源丰富,带独立的16 kB的指令Cache和16 kB数据Cache、LCD(液晶显示器)控制器、RAM控制器、NAND闪存控制器、3路UART、4路DMA、4路带PWM的定时器、并行I/O口、8路10位ADC、Tou
[嵌入式]
8051、ARM和DSP指令周期的测试与分析方法
在实时控制系统中,选择微控制器的指标时最重要的是计算速度的问题。指令周期是反映计算速度的一个重要指标,为此本文对三种最具代表性的微控制器(AT89S51单片机、ARM7TDMI核的LPC2114型单片机和TMS320F2812)的指令周期进行了分析和测试。为了能观察到指令周期,将三种控制器的GPIO口设置为数字输出口,并采用循环不断地置位和清零,通过观察GPIO口的波形变化得到整个循环的周期。为了将整个循环的周期与具体的每一条指令的指令周期对应起来,通过C语言源程序得到汇编语言指令来计算每一条汇编语言的指令周期。 1、 AT89S51工作机制及指令周期的测试 AT89S51单片机的时钟采用内部方式,时钟发生器对振荡脉冲进行
[单片机]
8051、<font color='red'>ARM</font>和DSP指令周期的测试与分析方法
英伟达并购ARM案会否获准?欧盟10月13日将给出答案
据路透社最新报道,英伟达周三 (8 日) 寻求欧盟寻求批准并购英国芯片开发商ARM,欧盟执委会已将 10 月 13 日订为裁决交易的初步期限,外界预料欧盟可能和英国主管机关表达相同疑虑,破坏英伟达预定明年初完成交易的如意算盘。 不过,欧盟执委会虽然设定初步期限,但由于竞争对手与芯片客户批评,仍可能将审查时间至少延长 4 个月。 一年前,英伟达这家全球最大的GPU和人工智能芯片提供商宣布收购ARM的交易后就立即引发了半导体行业的强烈反对。 长期以来,ARM 一直是一个中立的芯片提供商,将关键知识产权授权给众多芯片公司,包括高通、三星电子和苹果等,其中一些是英伟达的竞争对手。 高通曾公开表示不支持英伟达收购ARM。高通与Google
[手机便携]
ARM处理器与嵌入式系统
  引言   由于各种新型微处理器的出现和应用的不断深化,嵌入式系统在后PC时代得到了空前的发展。随着时间的推移和技术的进步,在工业控制和新兴的手持式应用等领域,用户体验成为产品成功的关键因素之一,越来越多的产品需要良好的用户界面、互联功能以及较强的数据处理能力,这对嵌入式处理器硬件、软件、教学等提出了新的要求。   1 嵌入式处理器与硬件   在处理器方面,目前大量的中、低端嵌入式应用,主要使用8/16位单片机。在国内,由于历史的原因,主要是以MCS51核为主的许多不同型号单片机,主要厂商有Atmel、Philips、Winbond、宏晶等。还有一些近几年发展较快的新型单片机,如PIC、AVR、MSP430系列等。这些单片
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved