首页 > 系统相关 >为什么要求内存对齐

为什么要求内存对齐

时间:2022-11-15 20:46:39浏览次数:35  
标签:为什么 字节 我们 访问 内存 对齐 cpu

当我们在我们的代码中申明变量时,我们通常是不用考虑也不会去做所谓的内存对齐的,因为这个工作本身是属于编译器去完成的。那我们的变量为什么不按照大小顺序地存放而是非要做所谓内存对齐?这个问题其实也是属于一个冲突问题,主要原因是内存的粒度是字节,即每一个BYTE都有唯一的地址,而cpu访存是按机器字(比如32位机器一次访存会取4Byte,无论我们访问的变量是什么类型的,比如我们只是获取一个char型变量,应该会做数据截断),理论上来说我们应该能够访问任意一个地址开始的四个字节。但是实际硬件是不支持的,这里我也是看到别人有说这个点,虽然抽象上,内存空间就像一块大的连续的一维数组,就是在我们真实的内存访问中,其实我们的是多个内存芯片同时工作,如图(别人的图用一下)。连续的四个字节其实是存储在这四个芯片上的,我们的地址,会转为offset,然后四个芯片同时给出自己offset的内容,组成四个字节传回给我们。比如我们有一段空间是0x00到0x40,如果我们按照四字节对齐访问,那我们cpu能直接访问的就应该是0x04,0x08,0x0c......这样的地址。比如0x00存了一个char型的变量,那我们其实就应该是访问了0x00然后拿出了4byte,按照数据类型截下来了相应的大小的数据(比如char 就是一个byte)。那比如0x01处还有一个放了一个int型的数据,这个四字节数据的前三个,应该是芯片2,3,4的offset0给出,最后一个字节应该是芯片1的offset1给出,这样至少需要两个offset,硬件不支持的话,肯定是没法访问的,这其实应该是所谓硬件支持不支持的关键原因。如果对齐访问的话,我们访问是四字节对齐的,那这个地址我们是无法直接访问到的,如果发生了对这个位置的访问,就会引起cpu fault。

 

 

如果被访问的内存地址不按照被访问的数据类型的位宽对齐,称为非对齐访问。比如int型占4个字节,则访问int型数据的内存地址需要按照4字节对齐。那比如在内存空间中,0x00是放的一个char型,0x01-0x04放了一个int型的数据,如果我们这个时候通过0x01这个地址访问int型变量,这就叫非对齐访问。其实只要硬件支持都没有麻烦事儿,最麻烦的事情是内存存放数据的格式,和cpu访问方式冲突。举个例子,我们把数据挨着放,不做对齐,但是cpu仅支持对齐访问,这个时候就会出现大问题,所以即使对齐访问可能会牺牲一部分存储空间,为了访问的方便,即使用了较大的空间存放较小的数据,但是确实这样有利于cpu访问处理数据。编译器可能会把这样的访存,优化成两次对齐访问,即取0x00开始的后三个字节,加上0x04开始的第一个字节,凑成完整的一个四字节,两次访存加拼接,去避免这个问题。还有当不支持非对齐访问时,强制数据类型转换也容易引起这个问题,还是刚刚的例子,如果我们的0x01的数据还是一个char型,那其实直接访问0x01这个位置的一个字节这个操作是内存对齐的方式,是没问题的。但是我们如果强制转换这个地址的数据为一个int型的,就会产生上述的第一个问题,这个时候如果非对齐访问不支持就会引起cpu fault。

 

由上可见,内存对齐还是很重要的,从硬要求看,有的cpu不管你想不想,人家压根就不支持,从效率优化来看,非对齐访问即使得以被硬件所实现那效率一定也低于对齐访问,或者是假装支持,把非对齐访问拆分成两次对齐访问加数据合并,这也说明效率至少比对齐访问低两倍,只有在一些内存资源紧张的地方,我们才会采用这样的方式,用时间效率换空间。

 

标签:为什么,字节,我们,访问,内存,对齐,cpu
From: https://www.cnblogs.com/luo-qi/p/16893721.html

相关文章

  • C++类的内存结构
     第一种这个类是个空类 sizeof会占用一个字节 newt也是占用一个字节但作为其他类的成员变量可能会占用1-2-4-8字节这个是类的内存对齐导致 第2种这......
  • 分页内存与非分页内存的疑惑
    参考:https://bbs.pediy.com/thread-160200.htm张帆《驱动详解》中讲到:当程序的中断请求级在DISPATCH_LEVEL之上时(包括DISPATCH_LEVEL层),程序只能使用非分页内存,否则将......
  • java 为什么要用补码_Java为什么使用补码进行计算的原因分析
    转自csdn---主要是前面的解释很通俗易懂,后面的没有细看,转过来以后查看方便。我们主要要解决的问题就是负数的表示,而众所周知,绝对值相等的两个正负数之和为0。假设我们有......
  • linux内存介绍
    [yunwei@192~]#freetotalusedfreesharedbuff/cacheavailableMem:323601921512724010232428767304......
  • 为什么我的HTTP代理用着用着就变慢了
    在日常生活中当我们想用一个IP的时候,代理ip是很常见的。但是,很多用户在购买HTTP代理使用的过程中,发现刚开始速度很快,用着用着就变慢了,影响了工作效率,这是为什么呢?......
  • Java 内存分区之什么是 CCS区 Compressed Class Space 类压缩空间
    https://blog.csdn.net/qq_27093465/article/details/106760961 Java内存分区之什么是CCS区CompressedClassSpace类压缩空间  了解到什么是ccs区,一般都是实际......
  • os::虚拟内存
    概念虚拟内存是程序,或者多个程序执行,内存没有这么大,但是却能执行,就是用到虚拟技术每个程序都有自己的空间,将空间分成多块每一块称为一页或者一个页面,然后通过分页技术映......
  • 为什么工业软件开发一般用的都是QT?
    这个说法不大准确吧,CAD、MATLAB、EDA、PRO-E、Proteus、POWERPCB是用的QT么?SAP、EBS(ORACLE)、LabView是用的QT么?西门子的工业控制类的软件(比如SIMATICSCADA)用的QT么?这些......
  • C温故补缺(十四):内存管理
    内存管理stdlib库中有几个内存管理相关的函数序号函数和描述1void*calloc(intnum,intsize);在内存中动态地分配num个长度为size个字节 的连续空间,并将......
  • 《程序员数学:斐波那契》—— 为什么不能用斐波那契散列,做数据库路由算法?
    作者:小傅哥博客:https://bugstack.cn源码:https://github.com/fuzhengwei/java-algorithms沉淀、分享、成长,让自己和他人都能有所收获!......