必须用mmap+MAP_HUGETLB分配并munmap释放,不可用new/malloc或free/delete;unique_ptr需自定义删除器调用munmap;环境需预配hugepages并确保权限。

如何用指针直接访问已映射的 Huge Pages 内存
不能直接用 new 或 malloc 拿到 Huge Pages 内存——它们走的是标准堆,底层不会自动使用 2MB/1GB 页。必须先通过系统接口(如 mmap)显式分配并锁定 huge page 区域,再用普通指针读写。
典型流程是:mmap 带 MAP_HUGETLB 标志申请内存,检查返回地址是否对齐(2MB 对齐是常见要求),然后像操作普通内存一样用 char*、int* 等指针访问。
- 务必检查
mmap返回值是否为MAP_FAILED,失败常因未配置 huge pages 或权限不足(需cap_ipc_lock或 root) - 指针算术完全可用,但要注意:跨 huge page 边界访问不会报错,但可能触发缺页异常或性能陡降(尤其当该 huge page 实际未驻留物理内存时)
- 不要对 huge page 映射区域调用
free或delete;必须用munmap释放
为什么 std::unique_ptr 不能直接管理 huge page 内存
std::unique_ptr 默认析构器调用 delete,而 huge page 内存不是 new 出来的,两者内存管理路径不兼容。强行绑定会导致 double free 或静默崩溃。
可行做法是自定义删除器:
立即学习“C++免费学习笔记(深入)”;
auto deleter = [](void* p) { munmap(p, SIZE); };
std::unique_ptr<char, decltype(deleter)> ptr(static_cast<char*>(addr), deleter);
- 删除器必须捕获 size(
munmap需要长度),不能只传指针 - 不能用
std::default_delete,也不能用 lambda 捕获局部变量(除非用std::function,但会引入虚函数开销) - 若需多态或复杂生命周期,建议封装为 RAII 类,而非依赖
unique_ptr的泛型构造
使用 mmap + MAP_HUGETLB 时的常见错误
最典型的失败不是代码写错,而是环境没配好。运行时报 Cannot allocate memory 或 Operation not supported 几乎都指向这个方向。
- Linux 下需提前分配 huge pages:例如
echo 128 > /proc/sys/vm/nr_hugepages(对应 128 个 2MB 页) - 非 root 用户需有
cap_ipc_lock能力,或改/proc/sys/vm/hugetlb_shm_group -
mmap必须指定MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB,漏掉任意一个标志都可能回退到普通页 - 某些内核版本要求
addr参数为nullptr(让内核选地址),硬指定地址易失败
指针访问 huge page 内存时的性能陷阱
拿到指针后读写很快,但“快”是有前提的:该 huge page 必须已实际分配物理帧并锁定在内存中。否则第一次访问仍会触发缺页中断,且因 huge page 缺页代价更高(一次要清零 2MB)。
- 用
mlock可确保立即驻留,但需额外权限,且失败时不抛异常,只返回 -1 - 避免频繁跨 huge page 边界跳转访问——虽然硬件支持,但 TLB miss 开销比普通页更大(huge page TLB 条目更少)
- 用
memset初始化整块 huge page 时,注意某些 libc 实现对 huge page 对齐内存有优化,但未对齐起始地址可能退化为逐字节写
真正难的不是怎么拿到指针,而是确认 huge page 确实被用了、锁住了、且访问模式匹配它的优势边界。随便贴个 MAP_HUGETLB 不等于性能提升。


















