Linux下的内存对齐函数

在Linux下内存对齐的函数包括posix_memalign, aligned_alloc, memalign, valloc, pvalloc,其各个函数的声明如下:

int posix_memalign(void **memptr, size_t alignment, size_t size);
void *memalign(size_t alignment, size_t size);
void *aligned_alloc(size_t alignment, size_t size);
void *valloc(size_t size);
void *pvalloc(size_t size);

1. posix_memalign函数: 分配size大小的字节,并将分配的内存地址存放在memptr中。分配的内存的地址将是alignment的倍数,且必须是2的幂次方和sizeof(void*)的倍数。如果size为0,则函数返回NULL或一个唯一的指针值,以便可以成功传递给free函数。如果分配成功返回0.

2. memalign函数: 是一个废弃的函数,分配size大小的字节,返回已分配的内存地址指针,其内存地址将是alignment的倍数,且必须是2的幂次方。如果分配失败返回NULL。

3. aligned_alloc函数: 用法与memalign函数相同,但是size大小应该alignment的倍数。如果分配失败返回NULL。

4. valloc函数: 是一个废弃的函数,分配size大小的字节,返回已分配的内存地址指针,其内存地址将是页大小(page size)的倍数。如果分配失败返回NULL。

5. pvalloc函数: 是一个废弃的函数,用法与valloc相似.如果分配失败返回NULL。

malloc函数总是返回8字节对齐的内存地址,在64bits上是16字节对齐。

以上所有函数均可以通过free函数进行释放。

alignas也可以用于内存对齐,可以使用alignof来判断是采用多少字节进行对齐,alignas和alignof要配对使用,否则单独调用alignof返回的结果是不准确的。

以下是测试代码(sample_memory_alignment.cpp):

#include <stdlib.h>
#include <malloc.h>
#include <iostream>

int main()
{
	for (int i = 0; i < 100; ++i) {
		void* p1 = nullptr;
		size_t alignment = 64;
		size_t size = 512;

		int ret = posix_memalign(&p1, alignment, size);
		void* p2 = memalign(alignment, size);
		void* p3 = aligned_alloc(alignment, size);
		void* p4 = valloc(size);
		void* p5 = pvalloc(size);
		void* p6 = malloc(size);

		size_t remainder = 0;
		remainder = (unsigned long)p1 % alignment;
		if (remainder != 0)
			fprintf(stderr, "posix_memalign don't align: %d\n", remainder);
		remainder = (unsigned long)p2 % alignment;
		if (remainder != 0)
			fprintf(stderr, "memalign don't align: %d\n", remainder);
		remainder = (unsigned long)p3 % alignment;
		if (remainder != 0)
			fprintf(stderr, "aligned_alloc don't align: %d\n", remainder);
		remainder = (unsigned long)p4 % alignment;
		if (remainder != 0)
			fprintf(stderr, "valloc don't align: %d\n", remainder);
		remainder = (unsigned long)p5 % alignment;
		if (remainder != 0)
			fprintf(stderr, "pvalloc don't align: %d\n", remainder);
		remainder = (unsigned long)p6 % alignment;
		if (remainder != 0)
			fprintf(stderr, "malloc don't algin: %d\n", remainder);

		struct Empty{};
		struct alignas(64) Empty64{};
		fprintf(stdout, "alignment: %d, %d, %d\n", alignof(Empty), alignof(Empty64), alignof(p6));
		
		free(p1); free(p2); free(p3); free(p4); free(p5); free(p6);
	}

	fprintf(stdout, "void* size: %d\n", sizeof(void*));

	return 0;
}

CMakeLists.txt内容如下:

PROJECT(samples_cplusplus)
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)

# 支持C++11
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O2 -std=c11")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -g -Wall -O2 -std=c++11")

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

FILE(GLOB samples ${PROJECT_SOURCE_DIR}/*.cpp)

FOREACH (sample ${samples})
	STRING(REGEX MATCH "[^/]+$" sample_file ${sample})
	STRING(REPLACE ".cpp" "" sample_basename ${sample_file})
	ADD_EXECUTABLE(test_${sample_basename} ${sample})
	TARGET_LINK_LIBRARIES(test_${sample_basename} pthread)
ENDFOREACH()

build.sh脚本内容如下:

#! /bin/bash

real_path=$(realpath $0)
dir_name=`dirname "${real_path}"`
echo "real_path: ${real_path}, dir_name: ${dir_name}"

new_dir_name=${dir_name}/build
mkdir -p ${new_dir_name}
cd ${new_dir_name}
cmake ..
make

cd -

编译及测试方法如下:首先执行build.sh,然后再执行./build/test_sample_memory_alignment即可。

GitHubhttps://github.com/fengbingchun/Linux_Code_Test 

猜你喜欢

转载自blog.csdn.net/fengbingchun/article/details/81292170