尝试映射大页面时mmap失败(1GB)

时间:2015-03-03 07:40:22

标签: c linux-kernel kernel

我做了什么:1。用root启用大页面(我的系统支持1MB大页面)

$echo 20 > /proc/sys/vm/nr_hugepages

2.将庞大的页面文件系统安装到/ mnt / hugepages

$mount -t hugetlbfs nodev /mnt/hugepages

3.在巨大的页面文件系统中创建文件

$touch /mnt/hugepages/hello

4.然后使用mmap将大页面映射到地址0,如下面的代码所示

   #define FILE_NAME "/mnt/hugepages/hello"
   #define PROTECTION (PROT_READ | PROT_WRITE) // page flag
   #define LENGTH (1024*1024*1024)     // huge page size
   #define FLAGS (MAP_SHARED)      //page flag
   #define ADDR (void *) (0x0UL)   //starting address of the page

   fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);    
   if (fd < 0) {                    // 
         perror("Open failed");
         exit(1);
    }

   // allocate a buffer using huge pages
   buf = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
   if (buf == MAP_FAILED) {
           perror("mmap");
           unlink(FILE_NAME);
           exit(1);
    }

该计划输出: mmap:无法分配内存

3 个答案:

答案 0 :(得分:2)

Linux仅支持私有匿名映射的大页面(不受文件支持)。即你只能为堆栈,数据和堆启用大表。

答案 1 :(得分:1)

目前尚不清楚OP是在谈论1GB页面大小还是在ARMv7上,并且确实有1MB的页面大小(主题与描述不符)。这个答案是指使用1GB页面大小。

无论如何,如果你想要1GB的页面大小,你必须在启动时启用它(除非你的内存非常干净,因为只有你拥有hugepagesz连续的可用内存才能分配大页面)。要启用gigabyte hugepages,请将 hugepagesz = 1GB hugepages = n 添加到GRUB_CMDLINE_LINUX,其中n是要添加的1GB页面的数量。

您现在可以使用get_huge_pages()( yah!)等接口使用1GB大页面,但仍然无法使用shm_get / mmap( boo!)进行分配。这两个都没有指定hugepagesz的机制,需要一个解决方法,将 default_hugepagesz = 1GB 设置为内核启动命令行的附加参数。

一旦你设置了所有三个参数告别TLB故障并沉浸在1GB页面大小的荣耀中!...除非你掌权,然后你应该沉浸在16GB页面大小的荣耀中;) 。

  # Script to create /hugepages mount point and enable 1GB hugepages
  # For RHEL (6) Systems!
  #
  #   MAKE SURE YOU KNOW WHAT THIS SCRIPT DOES BEFORE RUNNING!

  echo "hugetlbfs   /hugepages    hugetlbfs rw,mode=0777,pagesize=1G  0 0" \
  >> /etc/fstab
  mkdir /hugepages
  sed 's/rhgb quiet/hugepagesz=1GB default_hugepagesz=1GB hugepages=16 selinux=0/' /etc/default/grub > grub
  cp /etc/default/grub grub.old
  mv -f grub /etc/default/grub
  grub2-mkconfig  > /etc/grub2-efi.cfg

  # Now reboot

答案 2 :(得分:0)

请注意,您还需要使用ftruncate(2)来调整文件的大小,以便它实际保存您使用的内存量。 mmap(2)仍可用于零大小的文件,但在尝试访问内存时,您将获得SIGBUS

  

使用映射区域可能会产生以下信号:

     

...

     

SIGBUS尝试访问与文件不对应的缓冲区的一部分(例如,超出文件末尾,包括另一个进程截断文件的情况)。

(来自mmap(2)。)

要检查该区域是否真的使用了大页面,您可以检查/proc/[pid]/smaps(在Linux上的proc(5)中有记录)。检查内存区域VmFlags是否包含ht

修改

顺便看看libhugetlbfs了吗?