内存对齐理论

a.数据的对齐(alignment)
指数据的地址和由硬件条件决定的内存块大小之间的关系。一个变量的地址是它大小的倍数的时候,这就叫做自然对齐(naturally aligned)。
例如,对于一个32bit的变量,如果它的地址是4的倍数(地址的低两位是0--备注1),那么这就是自然对齐.
对齐的规则是由硬件引起的。一些体系的计算机在数据对齐这方面有着很严格的要求。在一些系统上,一个不对齐的数据的载入可能会引起进程的陷入。
在另外一些系统,对不对齐的数据的访问是安全的,但却会引起性能的下降。在编写可移植的代码的时候,对齐的问题是必须避免的,所有的类型都该自然对齐。 b.预对齐内存的分配
在大多数情况下,编译器和C库透明地帮你处理对齐问题。POSIX标明了通过malloc(),calloc(),和realloc()返回的地址对于任何的C类型来说都是对齐的。
在Linux中,这些函数返回的地址在32位系统是以8字节为边界对齐,在64位系统是以16字节为边界对齐的。有时候,对于更大的边界,程序员需要动态的对齐。
虽然动机是多种多样的,但最常见的是直接块I/O的缓存的对齐或者其它的软件对硬件的交互,因此,POSIX .1d提供一个叫做posix_memalign( )的函数 c.数据对齐的性能提升
对于现代计算机硬件来说,内存只能通过特定的对齐地址(比如按照机器字)进行访问。举个例子来说,
比如在64位的机器上,不管我们是要读取第0个字节还是要读取第1个字节,在硬件上传输的信号都是一样的。
因为它都会把地址0到地址7,这8个字节全部读到CPU,只是当我们是需要读取第0个字节时,丢掉后面7个字节,
当我们是需要读取第1个字节,丢掉第1个和后面6个字节。
假设我们要读取2个字节,这两个字节刚好落在两个机器字内时,就出现两次访问内存的情况,同时通过一些逻辑计算才能得到最终的结果。
因此,为了更好的提升性能,我们须尽量将结构体做到机器字(或倍数)对齐,而结构体中一些频繁访问的字段也尽量安排在机器字对齐的位置。 备注1:
二进制现象解释
对于二进制数 ***** 无论高5位怎么变化,该数一定8的倍数(对于二进制数 ****** 无论高6位怎么变化,该数一定4的倍数)
因为是二进制, ***** 除以 ,结果和 ***** 一致,相当于二进制数的每一位都降1阶,
那么 ***** 一共可以除以3个2,即可以除以8,因此 ***** 一定是8的倍数
/* 内存对齐 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string> #ifndef NGX_ALIGNMENT
#define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */
#endif /*
设计说明
sizeof(unsigned long)
在32位操作平台上,unsigned long 的大小是4个字节,恰巧32位平台的机器字也是4个字节
在64位操作平台上,unsigned long 的大小是8个字节,恰巧64位平台的机器字也是8个字节
*/ #define ngx_align_ptr(p, a) \
(unsigned char *) (((unsigned int) (p) + ((unsigned int) a - )) & ~((unsigned int) a - )) /*
设计说明:
ngx_align_ptr宏定义设计详解
(unsigned int) (p) 把地址当做整数进行操作,为了计算 整数p 加多少才是 a 的倍数 (unsigned int) (p) + ((unsigned int) a - 1 将 整数p 向上扩充,因为是内存对齐,地址只能向后跑。向前跑就可能内存越界
假设a是8,(((unsigned int) (p) + ((unsigned int) a - 1)) & ~((unsigned int) a - 1)) 只会影响 低3位,如果 整数p 在低位上有值,
那么 整数p 就会比原来小,而 整数p + a - 1 整数p的低3位上全部加1,如果 整数p 低3位上有值,肯定会产生进位,
这样可以确保操作后的 整数p 绝对比 原来的整数p 大 (((unsigned int) (p) + ((unsigned int) a - 1)) & ~((unsigned int) a - 1)) 假设a是8,该操作就会将 整数p 后3位变成0
*/ int main()
{
//示例用法
void * p = (void *)0x2379b1;
//进行内存对齐操作
p = ngx_align_ptr(p, NGX_ALIGNMENT);
return ;
}
posix_memalign

函数原型
int posix_memalign(void **memptr, size_t alignment, size_t size); 函数说明
调用posix_memalign( )成功时会返回size字节的动态内存,并且这块内存的地址是alignment的倍数。参数alignment必须是2的幂,
还是void指针的大小的倍数。返回的内存块的地址放在了memptr里面,函数返回值是0. 返回值
调用失败时,没有内存会被分配,memptr的值没有被定义,返回如下错误码之一:
EINVAL
参数不是2的幂,或者不是void指针的倍数。
ENOMEM
没有足够的内存去满足函数的请求。 注意
posix_memalign函数,errno不会被设置,只能通过返回值得到。
由posix_memalign( )获得的内存通过free( )释放

Sword 计算机内存对齐的更多相关文章

  1. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

  2. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

  3. C语言 结构体的内存对齐问题与位域

    http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...

  4. C语言结构体的内存对齐问题

    在C语言开发当中会遇到这样的情况: #include <stdio.h> struct test { int a; char b; }; int main(int argc, const ...

  5. 内存对齐与ANSI C中struct型数据的内存布局 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-3032209.html 当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将 ...

  6. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

  7. 内存对齐与ANSI C中struct型数据的内存布局

    当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不 ...

  8. 浅析内存对齐与ANSI C中struct型数据的内存布局-内存对齐规则

    这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密. 首先,至少有一点可以肯定,那就是ANSI C保证结构体中各字段在内存中出现的位置是随它们的声明顺序依次递增的,并且第一个字段的 ...

  9. C/C++内存对齐详解

    1.什么是内存对齐 还是用一个例子带出这个问题,看下面的小程序,理论上,32位系统下,int占4byte,char占一个byte,那么将它们放到一个结构体中应该占4+1=5byte:但是实际上,通过运 ...

随机推荐

  1. linux内核模块编译makefile

    linux内核可加载模块的makefile 在开发linux内核驱动时,免不了要接触到makefile的编写和修改,尽管网上的makefile模板一大堆,做一些简单的修改就能用到自己的项目上,但是,对 ...

  2. 一小部分用python进行MD5加密的小技巧

    上个图 要求计算出开头为ae3da且盐值为3c6e的字符串 简单的思路就是直接进行枚举,然后筛选符合条件的MD5加密字符,代码如下 #-*- coding:utf- -*- import hashli ...

  3. 移动端初始化常用JavaScript代码

    移动端常用js分享 1.把手机屏幕等分10分(我用的是这种形式),用rem来计算那些需要自适应. <script type="text/javascript"> (fu ...

  4. K8s基本概念入门

    序言 没等到风来,绵绵小雨,所以写个随笔,聊聊k8s的基本概念. k8s是一个编排容器的工具,其实也是管理应用的全生命周期的一个工具,从创建应用,应用的部署,应用提供服务,扩容缩容应用,应用更新,都非 ...

  5. python使用print写文件

    刚刚看sumo的官方教程,有一段代码是生成配置文件,发现python中的print函数也可以写文件. with open("data/cross.rou.xml", "w ...

  6. 《exception》第九次团队作业:Beta冲刺与验收准备(大结局)

    一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件黑盒测试技术:2.学会编制软件项目 ...

  7. 8-html表格

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  8. 洛谷 SP338 ROADS - Roads 题解

    思路 dfs(只不过要用邻接表存)邻接表是由表头结点和表结点两部分组成,其中表头结点存储图的各顶点,表结点用单向链表存储表头结点所对应顶点的相邻顶点(也就是表示了图的边).在有向图里表示表头结点指向其 ...

  9. 《OKR工作法》–让所有人承担自己的职责

    <OKR工作法>中提到了一个创业故事,TeaBee,创业的目标是让喜欢喝茶的人喝到好茶. 创业初期作为首席执行官的汉娜和作为总裁的杰克就在将茶叶提供给餐厅还是餐厅供应商上产生了分歧,随后他 ...

  10. 小程序支付及H5支付前端代码小结

    小程序支付和H5支付前端都不需要引入其他的js , 只需要后台将相关的参数 ( timeStamp: '', nonceStr: '', package: '', signType: 'MD5', p ...