Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68149
  • 博文数量: 19
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 239
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-08 15:35
文章分类

全部博文(19)

文章存档

2012年(2)

2011年(17)

我的朋友

分类: LINUX

2011-10-08 15:57:40

MmapSysAllocator

void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,

                              size_t alignment) {

#ifndef HAVE_MMAP

  failed_ = true;

  return NULL;

#else

  // Check if we should use mmap allocation.

  // FLAGS_malloc_skip_mmap starts out as false (its uninitialized

  // state) and eventually gets initialized to the specified value.  Note

  // that this code runs for a while before the flags are initialized.

  // Chances are we never get here before the flags are initialized since

  // sbrk is used until the heap is exhausted (before mmap is used).

  if (FLAGS_malloc_skip_mmap) {

    return NULL;

  }

//上面的处理和前面brk的处理一样,都是根据参数判断是否采用mmap分配内存

  // Enforce page alignment

  if (pagesize == 0) pagesize = getpagesize();//获取page size的大小

  if (alignment < pagesize) alignment = pagesize;

  size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;

//pagesize进行对齐

  if (aligned_size < size) {

    return NULL;

  }

  size = aligned_size;

 

  // "actual_size" indicates that the bytes from the returned pointer

  // p up to and including (p + actual_size - 1) have been allocated.

  if (actual_size) {

    *actual_size = size;

  }

 

  // Ask for extra memory if alignment > pagesize

  size_t extra = 0;

  if (alignment > pagesize) {

    extra = alignment - pagesize;

  }

//判断alignment是否大于pagesize,如果大于那么需要一个额外的size来进行补充,以满足页对齐

  // Note: size + extra does not overflow since:

  //            size + alignment < (1<

  // and        extra <= alignment

  // therefore  size + extra < (1<

  void* result = mmap(NULL, size + extra,

                      PROT_READ|PROT_WRITE,

                      MAP_PRIVATE|MAP_ANONYMOUS,

                      -1, 0);

  if (result == reinterpret_cast(MAP_FAILED)) {

    failed_ = true;

    return NULL;

  }

//调用mmap进行vma分配,如果分配失败,设置failed_true

  // Adjust the return memory so it is aligned

  uintptr_t ptr = reinterpret_cast(result);

  size_t adjust = 0;

  if ((ptr & (alignment - 1)) != 0) {

    adjust = alignment - (ptr & (alignment - 1));

  }

 

  // Return the unused memory to the system

  if (adjust > 0) {

    munmap(reinterpret_cast(ptr), adjust);

  }

  首先判断adjust是否大于0,如果大于0代表着在map的是否为了迎合alignment进行了调整,那么把这部分内存返还给系统,不过返回的位置是在mmap出来空间的头上

  if (adjust < extra) {

    munmap(reinterpret_cast(ptr + adjust + size), extra - adjust);

  }

//然后判断是不是为了页对齐申请了额外的空间如果是,那么也将此空间返还给系统

  ptr += adjust;

  return reinterpret_cast(ptr);//返回经过调整后的指针

#endif  // HAVE_MMAP

}

 

DevMemSysAllocator

 

void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,

                                size_t alignment) {

#ifndef HAVE_MMAP

  failed_ = true;

  return NULL;

#else

  static bool initialized = false;

  static off_t physmem_base;  // next physical memory address to allocate

  static off_t physmem_limit; // maximum physical address allowed

  static int physmem_fd;      // file descriptor for /dev/mem

 

  // Check if we should use /dev/mem allocation.  Note that it may take

  // a while to get this flag initialized, so meanwhile we fall back to

  // the next allocator.  (It looks like 7MB gets allocated before

  // this flag gets initialized -khr.)

  if (FLAGS_malloc_devmem_start == 0) {

    // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to

    // try us again next time.

    return NULL;

  }

//同样的进行check相关的flag是否置位

  if (!initialized) {

    physmem_fd = open("/dev/mem", O_RDWR);

    if (physmem_fd < 0) {

      failed_ = true;

      return NULL;

    }

    physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL;

    physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL;

    initialized = true;

  }

//如果尚未初始化physmem_fd,那么进行初始化,通过open打开相应的mem设备”/dev/mm”,并设置相关的参数physmem_basephysmem_limit

  // Enforce page alignment

  if (pagesize == 0) pagesize = getpagesize();

  if (alignment < pagesize) alignment = pagesize;

  size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;//调整size的大小,根据alignment对齐。

  if (aligned_size < size) {

    return NULL;

  }

  size = aligned_size;

 

  // "actual_size" indicates that the bytes from the returned pointer

  // p up to and including (p + actual_size - 1) have been allocated.

  if (actual_size) {

    *actual_size = size;

  }

 

  // Ask for extra memory if alignment > pagesize

  size_t extra = 0;

  if (alignment > pagesize) {

    extra = alignment - pagesize;

  }

//判断alignment是否大于pagesize,如果大于那么需要一个额外的size来进行补充,以满足页对齐

  // check to see if we have any memory left

  if (physmem_limit != 0 &&

      ((size + extra) > (physmem_limit - physmem_base))) {

    failed_ = true;

    return NULL;

  }

//判断申请的内存有没有超过限制Physical memory limit

  // Note: size + extra does not overflow since:

  //            size + alignment < (1<

  // and        extra <= alignment

  // therefore  size + extra < (1<

  void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,

                      MAP_SHARED, physmem_fd, physmem_base);

//通过mmap在设备/dev/mem上面进行分配

  if (result == reinterpret_cast(MAP_FAILED)) {

    failed_ = true;

    return NULL;

  }

  uintptr_t ptr = reinterpret_cast(result);

 

  // Adjust the return memory so it is aligned

  size_t adjust = 0;

  if ((ptr & (alignment - 1)) != 0) {

    adjust = alignment - (ptr & (alignment - 1));

  }

 

  // Return the unused virtual memory to the system

  if (adjust > 0) {

    munmap(reinterpret_cast(ptr), adjust);

  }

  if (adjust < extra) {

    munmap(reinterpret_cast(ptr + adjust + size), extra - adjust);

  }

 

  ptr += adjust;

  physmem_base += adjust + size;

 

  return reinterpret_cast(ptr);

#endif  // HAVE_MMAP

}

//mmap分配一样进行动态调整。

阅读(791) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~