Linux C ++中的页面对齐的内存分配

时间:2018-09-30 09:15:31

标签: c++ linux memory-management dynamic-memory-allocation mmu

假设,我需要在Linux64 C ++应用程序中分配一个较大的Vector。 我执行以下操作:

int main()
{
  std::vector<int> v;
  v.resize(2000);

  std::cout << &v[0] << std::endl;

  return 0;
}

这将在我的笔记本电脑上打印0x7ffc2a177450,该笔记本电脑是字对齐的。但是,Vector大小为2000 * 4B = 8kB,恰好是我的4kB页面Ubuntu系统上的2页。

问题:如何将我的Vector放在页面的开头,这样分配就可以在物理内存的2个页面中产生?理想情况下,物理内存中的两个页面也应该是连续的。谢谢!

1 个答案:

答案 0 :(得分:5)

您可以定义页面分配器:

#include <sys/user.h>
#include <sys/mman.h>
#include <cstddef>
#include <new>
template<class T>
struct page_allocator{
    using value_type = T;
    static auto mem_size_for(std::size_t n){
      n = n * sizeof(T);
      return (n & (PAGE_MASK)) + (n & ~(PAGE_MASK) ? PAGE_SIZE:0);
      }
    T* allocate(std::size_t n){
      auto p = mmap(0, mem_size_for(n)
                   ,PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
      if (p==MAP_FAILED) throw std::bad_alloc{};
      return static_cast<T*>(p);
      }
    void deallocate(T* p,std::size_t n){
      munmap(p,mem_size_for(n));
      }
    constexpr bool operator==(page_allocator)noexcept{return true;}
    constexpr bool operator!=(page_allocator)noexcept{return false;}
  };

并以这种方式使用它:

int main()
{
  std::vector<int,page_allocator<int>> v;
  v.resize(PAGE_SIZE/sizeof(int));

  std::cout << &v[0] << std::endl;

  return 0;
}

其他选项,使用posix_memalign:

#include <cstddef>
#include <new>
#include <stdlib.h>
template<class T>
struct memalign_allocator{
    using value_type = T;
    T* allocate(std::size_t n){
      void* p;
      if (posix_memalign(&p,PAGE_SIZE,n*sizeof(T))) throw std::bad_alloc{};
      return static_cast<T*>(p);
      }
    void deallocate(T* p,std::size_t n){
      free(p);
      }
    constexpr bool operator==(memalign_allocator)noexcept{return true;}
    constexpr bool operator!=(memalign_allocator)noexcept{return false;}
  };

使用aligned_alloc会更好。

相关问题