Linux 上内存映射文件的大页面
Huge pages for memory mapped files on Linux
我想在 Linux 3.13.
上对内存映射文件使用大页面
开始,在 Ubuntu 我这样做是为了分配 10 个大页面:
sudo apt-get install hugepages
sudo hugeadm --pool-pages-min=2048K:10
那我运行这个测试程序:
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
size_t size = 2 * 1024 * 1024; /* 1 huge page */
int fd = open("foo.bar", O_RDWR|O_CREAT, 0666);
assert(fd >= 0);
int rc = ftruncate(fd, size);
assert(rc == 0);
void* hint = 0;
int flags = MAP_SHARED | MAP_HUGETLB;
void* data = mmap(hint, size, PROT_READ|PROT_WRITE, flags, fd, 0);
if (data == MAP_FAILED)
perror("mmap");
assert(data != MAP_FAILED);
}
它总是因 EINVAL 而失败。如果您将 flags
更改为 MAP_PRIVATE|MAP_ANONYMOUS
那么它可以工作,但当然它不会向文件写入任何内容。
我也试过在 mmap()
之后使用 madvise()
而没有 MAP_HUGETLB
:
rc = madvise(data, size, MADV_HUGEPAGE);
if (rc != 0)
perror("madvise");
assert(rc == 0);
如果未使用 MAP_ANONYMOUS
,这也会失败 (EINVAL
)。
有什么方法可以在磁盘上启用带有内存映射文件的大页面吗?
需要说明的是,我正在寻找一种在 C 语言中执行此操作的方法——我并不是在寻求一种适用于现有可执行文件的解决方案(这样问题就属于 SuperUser)。
您使用的底层文件系统似乎不支持使用大页面的内存映射文件。
例如,对于 ext4,此支持仍在开发中 as of January 2017,尚未包含在内核中(截至 2017 年 5 月 19 日)。
如果您 运行 应用了该补丁集的内核,请注意您需要在文件系统挂载选项中启用大页面支持,例如将 huge=always
添加到 [=] 的第四列11=] 用于所需的文件系统,或使用 sudo mount -o remount,huge=always /mountpoint
.
这里有一个混淆:大页面可以通过原始内核接口使用 or/and 通过用户 space 库(libhugetlbfs)和伴随工具(例如 hugeadm
)。
如果你想mmap()
一个内存区变成大页面。您正在使用“原始内核接口”。要做到这一点,.
中有一个食谱
如果您想使用用户 space 库 (libhugetlbfs),请从 manuals of the tools and the manual of the API.
获取帮助
我想在 Linux 3.13.
上对内存映射文件使用大页面开始,在 Ubuntu 我这样做是为了分配 10 个大页面:
sudo apt-get install hugepages
sudo hugeadm --pool-pages-min=2048K:10
那我运行这个测试程序:
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
size_t size = 2 * 1024 * 1024; /* 1 huge page */
int fd = open("foo.bar", O_RDWR|O_CREAT, 0666);
assert(fd >= 0);
int rc = ftruncate(fd, size);
assert(rc == 0);
void* hint = 0;
int flags = MAP_SHARED | MAP_HUGETLB;
void* data = mmap(hint, size, PROT_READ|PROT_WRITE, flags, fd, 0);
if (data == MAP_FAILED)
perror("mmap");
assert(data != MAP_FAILED);
}
它总是因 EINVAL 而失败。如果您将 flags
更改为 MAP_PRIVATE|MAP_ANONYMOUS
那么它可以工作,但当然它不会向文件写入任何内容。
我也试过在 mmap()
之后使用 madvise()
而没有 MAP_HUGETLB
:
rc = madvise(data, size, MADV_HUGEPAGE);
if (rc != 0)
perror("madvise");
assert(rc == 0);
如果未使用 MAP_ANONYMOUS
,这也会失败 (EINVAL
)。
有什么方法可以在磁盘上启用带有内存映射文件的大页面吗?
需要说明的是,我正在寻找一种在 C 语言中执行此操作的方法——我并不是在寻求一种适用于现有可执行文件的解决方案(这样问题就属于 SuperUser)。
您使用的底层文件系统似乎不支持使用大页面的内存映射文件。
例如,对于 ext4,此支持仍在开发中 as of January 2017,尚未包含在内核中(截至 2017 年 5 月 19 日)。
如果您 运行 应用了该补丁集的内核,请注意您需要在文件系统挂载选项中启用大页面支持,例如将 huge=always
添加到 [=] 的第四列11=] 用于所需的文件系统,或使用 sudo mount -o remount,huge=always /mountpoint
.
这里有一个混淆:大页面可以通过原始内核接口使用 or/and 通过用户 space 库(libhugetlbfs)和伴随工具(例如 hugeadm
)。
如果你想mmap()
一个内存区变成大页面。您正在使用“原始内核接口”。要做到这一点,
如果您想使用用户 space 库 (libhugetlbfs),请从 manuals of the tools and the manual of the API.
获取帮助