如何分配页面大小对齐的内存?

时间:2014-02-04 10:53:35

标签: c linux memory memory-management

我需要分配应该与页面大小对齐的内存。我需要将此内存传递给ASM代码,该代码计算所有数据块的xor。我需要使用malloc()执行此操作。

5 个答案:

答案 0 :(得分:9)

您应该使用此功能。

如果不能,无论出于何种原因,通常这样做的方法是将块大小添加到分配大小,然后使用整数数学技巧来舍入指针。

这样的事情:

/* Note that alignment must be a power of two. */
void * allocate_aligned(size_t size, size_t alignment)
{
  const size_t mask = alignment - 1;
  const uintptr_t mem = (uintptr_t) malloc(size + alignment);
  return (void *) ((mem + mask) & ~mask);
}

这还没有经过深刻的测试,但你明白了。

请注意,以后找不到适当的指针free()是不可能的。要解决这个问题,我们必须添加一些额外的机制:

typedef struct {
  void *aligned;
} AlignedMemory;

AlignedMemory * allocate_aligned2(size_t size, size_t alignment)
{
  const size_t mask = alignment - 1;
  AlignedMemory *am = malloc(sizeof *am + size + alignment);
  am->aligned = (void *) ((((uintptr_t) (am + 1)) + mask) & ~mask);
  return am;
}

这会稍微包装指针技巧,并为您提供一个可以free()的指针,但是您需要取消引用aligned指针才能获得正确对齐的指针。

答案 1 :(得分:7)

我认为只有malloc才有可能。您可以使用memalign()

char *data = memalign(PAGESIZE, alloc_size);

其中PAGESIZE是页面大小,alloc_size是要分配的内存大小。

可以使用sysconf(_SC_PAGESIZE)找到页面的大小。

答案 2 :(得分:6)

使用posix_memalign获取已对齐的内存。

注意:valloc& memalign两者都已废弃。

答案 3 :(得分:2)

使用valloc而不是malloc - 它与malloc具有相同的签名,但它会分配页面对齐的内存。请注意,您仍然使用free()随后释放内存。

另请注意,valloc在技术上已过时,因此请考虑使用posix_memalign,尽管这不是malloc的简单替代,因为它具有非常不同的函数签名。

答案 4 :(得分:0)

//面向Linux, //看我的骗术来安排自己

我刚刚编写了一个程序,该程序必须分配与硬件页面对齐的内存;以下是包含main()函数的程序的 body

main()函数调用Func_a()函数,该函数调用Func_b()函数,该函数调用上述Func_a()函数,依此类推……递归且无停止条件,从而无限期地烧写程序堆栈,最终导致SIGSEGV。

这对您有帮助吗?

#include "Func_A.h"
#include "Func_B.h"


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define STACK_SIZE (1024 * 1024)

int main(void)
{
  // Allocate a 2nd stack for the SIG_SEGV signal handler
  long pgsz = sysconf(_SC_PAGESIZE);
  printf("Page size is %ld\n", pgsz);

  long stacksize = STACK_SIZE;

  long sigstkpages = (STACK_SIZE + (pgsz - 1) ) / pgsz;

  void* newstack = calloc(sigstkpages, pgsz);
  if (NULL == newstack)
  {
    perror("calloc()\n");
    exit(2);
  }
  newstack = (void*) (((((long) newstack) + (pgsz - 1)) / pgsz) * pgsz);
  void* newstackhigh = (void*) (((long) newstack) + (stacksize - 1));
  stacksize = (newstackhigh - newstack) + 1;
  printf("Stack size is %ld\n", stacksize);

  printf("New Stack spans %p-%p  (%ld pages)\n", newstack, newstackhigh, sigstkpages);

  a();
}

其输出为:

页面大小为4096 堆栈大小为1048576 新堆栈跨越0x7f28435cd000-0x7f28436ccfff(256页) 错误分割(核心已转储)

预计将在此处进行转储。