什么是内存对齐
计算机系统要求基本类型数据在内存中存放的首地址的值是某个数K(通常是4或8)的倍数,这就是内存对齐。
为什么要内存对齐
处理器是按字节块存取内存的,例如:以4字节、8字节等为单位存取内存。
(这里做个解释,不知道是否准确:32位CPU因为数据总线是32位,所以可以一次读取32位内存数据。内存地址是32位的,如0x00000000~0xffffffff;每一个地址存放一个字节的数据;至于取出的数据是多少位取决于数据类型,比如,如果是int类型的数据,那么一次读取四个字节的数据,即从当前地址到往后三个地址的数据组成一个数据读出;如果是char类型的变量,一次只读取一个字节的数据。)
现在看一个例子,假如没有内存对齐机制,数据存放内存的首地址可以是任意的,现在一个int变量存放在从地址1开始的连续四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器。这需要做很多工作。
现在有了内存对齐,int类型数据只能存放在按照对齐规则的内存中,比如说0地址开始的内存。那么现在该处理器在取数据时一次性就能将数据读出来了,而且不需要做额外的操作,提高了效率。
posix_memalign内存对齐函数
在大多数情况下,编译器和C库透明地帮你处理对齐问题。POSIX 标明了通过malloc( ), calloc( ), 和 realloc( ) 返回的地址对于任何的C类型来说都是对齐的。在Linux中,这些函数返回的内存块地址都是8的倍数(如果是64位系统,则为16的倍数)。但是对于更大的边界,例如页面,程序员需要动态的对齐。因此,POSIX 1003.1d提供一个叫做 posix_memalign( )的函数:
int posix_memalign (void **memptr,
size_t alignment,
size_t size);
参数:
memptr:指向申请的动态内存的地址
alignment:这块内存的首地址是256的倍数
size:这块内存的大小
char* buf;
int ret = posix_memalign(&memptr, 256, 10240);
if (ret)
return -1;
free(buf);
注意:
1、alignment必须是sizeof(void*)与2的整数次幂两者间的乘积。
2、size 必须是 alignment 的2的整数幂次倍
3、对于这个函数,errno 不会被设置,只能通过返回值得到,返回值为0表示内存申请成功
参考文献: