Linux内核巨页代码学习

破解 1GiB 巨页与 KHO 冲突:Linux 内核 Extended Scratch 机制与 Radix 树摘要算法深度解析 既然巨页不能在初始 Scratch 中分配,Early Boot 阶段去哪里找足够的物理内存?Patchset 引入了[ 原始 Preserved Radix Tree ] ──(单次遍历)──► [ Digest Radix Tree (1GiB 粒度) ](包含分散的 4KB, 2MB 保留页) (按 1GiB 物理块汇总的位图树)│▼[ 遍历 Digest 树找到空隙 ]│▼[ 标记为 Extended Scratch ]单次遍历与摘要(Digest) 阅读详情
巨页的实现,涉及到两个模块:hugetlb和hugetlbfs。


hugetlb相当于是huge page页面管理者,页面的分配及释放,都由此模块负责。
hugetlbfs则用于向用户提供一套基于文件系统的巨页使用界面,其下层功能的实现,则依赖于hugetlb。


1.    hugetlb模块

struct  hstate  hstates[HUGE_MAX_HSTATE];
上面定义了一个hstate数组,每个元素是一个巨页池。
不同的巨页池,其巨页尺寸是不一样的,例如2M的,4M的,1G的等等。
系统中可能会有多个巨页池,每一个池的巨页尺寸都是不一样的。
max_hstate标识当前有多少个hstate,即数组的前多少个元素是有效的。
默认的话,hugetlb_init中会创建一个hstate,其page size是默认大小,此hstate也就成了默认的hstate。
如果hugetlb.c被编译进内核,并且内核启动的时候,命令行参数中有hugepagesz=选项。
那么就会调用setup_hugepagesz进行处理,setup_hugepagesz应该会在hugetlb_init之前执行。
setup_hugepagesz中会调用hugetlb_add_hstate添加一个hstate,其pagesize大小为命令行参数中指定的大小。
每一个hstate,在/sys/kernel/mm/hugepages下面会有一个目录与之对应。通过读写此目录下的文件,即可实现对此hstate的各种属性的查看与修改。例如,可以查看或修改此hstate的页面数量。
例如,下面的命令将2M巨页池的页面数设置为N
echo  N  > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
如果N小于当前池中的页面数量,则会归还相应的页面给内核。
如果N为0,就全还给内核了。
但是,必须等程序释放了内存,这些内存才会真正还给内核。
如果程序还没释放,则这种需要释放还没释放的页面数,可以通过如下文件得知。
/sys/kernel/mm/hugepages/hugepages-2048kB/surplus_hugepages


另外,也可以通过sysctl命令,来修改巨页的配置。


copy_bootdata函数 (arch\x86\kernel\head64.c)中,会根据dpdk的设置来设置巨页相关的命令行参数。
当前系统具体是什么参数,可以在host上查看:cat /proc/cmdline
Hugepagesz参数规定了巨页尺寸。
Hugepages规定了页面数量。其页面在内核上电时,由hugetlb_nrpages_setup函数申请。


2.    hugetlbfs模块

hugetlbfs在加载时,会向内核注册hugetlbfs文件系统,并mount hugetlbfs文件系统到内核中,结果保存到hugetlbfs_vfsmount中。这个mount,没有使用什么参数,因此对应到默认的hstate。


3.    使用巨页

有两种方式,mmap方式和共享内存方式(shmget/shmat)。
但是,无论是通过哪种方式,最终都是通过对一个hugetlbfs类型的文件做内存映射而实现的(通过file->f_op->mmap完成)。


a.    mmap方式
这种方式,需要先通过如下命令mount一个hugetlbfs文件系统,通过pagesize指定页面大小。
mount -t hugetlbfs none /mnt/path/to/hugetlbfs -o pagesize=2048K
这样的话,新挂载的文件系统,与页面大小为2048K的hstate相关联。。
接下来,在/mnt/path/to/hugetlbfs下面创建文件,然后打开文件并通过mmap进行内存映射即可。


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>

#define    ERR_DBG_PRINT(fmt, args...) \
    do \
    { \
        printf("ERR_DBG:%s(%d)-%s:\n"fmt": %s\n", __FILE__,__LINE__,__FUNCTION__,##args, strerror(errno)); \
    } while (0)


/* mmap方式可以使用指定尺寸的巨页池 */
int main(int argc, char *argv[])
{
    int ret = system("mount -t hugetlbfs none /home/shared/sunmingbao/hugetlb_test -o pagesize=2048K");
    int fd = open("/home/shared/sunmingbao/hugetlb_test/hehe.txt", O_CREAT | O_RDWR, 0755);
    char *huge_mem = mmap(NULL, 2048*1024*5, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);


    if (ret<0)
    {
        ERR_DBG_PRINT("mount fail:");
        return 0;
    }

    if (fd<0)
    {
        ERR_DBG_PRINT("open fail:");
        return 0;
    }

    if (-1 == (int)(unsigned long)huge_mem)
    {
        ERR_DBG_PRINT("mmap fail:");
        return 0;
    }

    printf("press any key to access huge page\n");
    getchar();


    memset(huge_mem, 0, 2048*1024*5);

    printf("press any key to delete huge page\n");
    getchar();

    /* 下面代码一执行,内存就释放回巨页池了 */
    if (unlink("/home/shared/sunmingbao/hugetlb_test/hehe.txt")==-1)
        ERR_DBG_PRINT("unlink fail:");

    return 0;
}




b.    共享内存方式
这种方式,不需要上面提到的mount及创建文件操作。直接用shmget和shmat,即可使用巨页内存。
虽然用户没有mount及创建文件,但shmget内部还是创建了一个文件,并且是在上面提到的hugetlbfs_vfsmount挂载点下面。这样的话,就与mmap方式殊途同归了。hugetlbfs_vfsmount挂载点对应的是默认的hstate,因此所用巨页的页面大小也是默认的。


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

#define    ERR_DBG_PRINT(fmt, args...) \
    do \
    { \
        printf("ERR_DBG:%s(%d)-%s:\n"fmt": %s\n", __FILE__,__LINE__,__FUNCTION__,##args, strerror(errno)); \
    } while (0)


/* shmget方式只能使用默认尺寸的巨页池 */
int main(int argc, char *argv[])
{
    key_t  our_key = ftok("/home/shared/sunmingbao/hello.c", 6);
    int shm_id = shmget(our_key, 2048*1024*5, IPC_CREAT|IPC_EXCL|SHM_HUGETLB);
    char *huge_mem = shmat(shm_id, NULL, 0);


    if (-1 == (int)our_key)
    {
        ERR_DBG_PRINT("ftok fail:");
        return 0;
    }

    if (-1 == shm_id)
    {
        ERR_DBG_PRINT("shmget fail:");
        return 0;
    }

    if (-1 == (int)(unsigned long)huge_mem)
    {
        ERR_DBG_PRINT("shmat fail:");
        return 0;
    }

    printf("press any key to access huge page\n");
    getchar();


    memset(huge_mem, 0, 2048*1024*5);

    printf("<span style="font-family: Arial, Helvetica, sans-serif;">press any key to delete huge page</span>\n");
    getchar();


    /* 下面代码一执行,内存就释放回巨页池了 */
    shmdt(huge_mem);
    if (shmctl(shm_id, IPC_RMID, NULL)==-1)
        ERR_DBG_PRINT("shmctl fail:");

    return 0;
}



LLM 助力的 Linux 内核革新与 1GB 巨页演进 本文探讨了大型语言模型(LLM)在Linux内核开发中的应用现状与挑战。文章指出,内核开发者主要将LLM用作辅助工具,包括问题推演、原型设计、代码预审和文档撰写等场景,但强调"人类全责"原则。通过分析两个典型案例——改进1GB巨页分配的"超页块"方案和虚拟机内存追踪补丁,揭示了LLM辅助开发的两种命运:前者因过度依赖LLM生成低质量代码而遭社区批评,后者通过严格人工把关获得认可。文章特别剖析了hugetlbfs机制的技术原理,并指出成功的LLM应用需要资深开发者的架构 阅读详情

相关推荐

Linux内存管理(9):HugePage

巨页文件系统(HUGETLBFS)、透明巨页(Transparent HugePage, THP)

zhang_shuaifeng的博客 673

hugetlbfs的使用测试

hugetlbfs CPU缓存中有一组缓存专门用于缓存TLB,但其大小是有限的。当采用的默认页面大小为 4KB,其产生的TLB较大,因而将会产生较多 TLB Miss 和缺页中断,从而大大影响应用程序的性能。操作系统以 2MB 甚至更大作为分页的单位时,将会大大减少 TLB Miss 和缺页中断的数量,显著提高应用程序的性能。这也正是 Linux 内核引入大页面支持的直接原因。好处是很明显的,假设应用程序需要 2MB 的内存,如果操作系统以 4KB 作为分页的单位,则需要 512 个页面,进而在 TL

weixin_48101150的博客 4618

【CGroup原理篇V1】十、HugeTLB子系统

HugeTLB控制器可以在cgroup文件系统被挂载的时候被创建。

从0到1,突破自己 1216

Linux内核巨页代码解析和使用

前言 巨页的实现,涉及到两个模块:hugetlb 和 hugetlbfs。 hugetlb 相当于是 huge page 页面管理者,页面的分配及释放,都由此模块负责。 hugetlbfs 则用于向用户提供一套基于文件系统的巨页使用界面,其下层功能的实现,则依赖于 hugetlb。 目录 1、hugetlb模块 2、hugetlbfs模块 3、使用巨页 3.1、 mmap方式 3.2...

3593

Linux内存管理专题 - 第17章:HugeTLB

使用预分配的固定大小的大内存页(通常2MB或1GB)减少TLB miss,提高内存访问性能特别适合需要大内存工作集的应用(如数据库、科学计算等)fill:#333;color:#333;color:#333;fill:none;常规4KB页高TLB压力HugeTLB页减少TLB条目降低TLB miss率。

2301_79143213的博客 438

Mac本地大模型实战指南:Ollama+Metal+Apple Silicon深度优化

大语言模型(LLM)本地化部署正成为开发者关键技术能力,其核心在于推理效率、硬件适配与成本控制。Apple Silicon凭借统一内存架构(UMA)和Neural Engine,为本地LLM运行提供了独特优势;Metal加速则显著提升GPU计算吞吐,使Gemma 4、Qwen 3.5等模型在M系列Mac上实现低延迟、高精度、离线可用的工程落地。相比云端API,本地方案规避了token计费、网络依赖与数据外泄风险,特别适用于企业文档处理、实时语音分析、私有知识库检索等强隐私、低时延场景。本文聚焦Mac平台,系

weixin_33443333的博客 352

Linux修改巨页内存,Linux内核巨页代码学习

巨页的实现,涉及到两个模块:hugetlb和hugetlbfs。hugetlb相当于是huge page页面管理者,hugetlbfs则用于向用户提供一套基于文件系统的巨页使用界面,其下层功能的实现,则依赖于hugetlb。1. hugetlb模块struct hstate hstates[HUGE_MAX_HSTATE];上面定义了一个hstate数组。每一个hstate相当于一个huge...

weixin_29006187的博客 738

双向晶闸管交流调压基础知识及Multisim电路仿真

本文介绍了双向晶闸管交流调压电路的工作原理及应用。该电路由双向晶闸管、RC移相电路和双向触发二极管组成,通过调节电位器改变触发角实现电压调节。当电位器阻值减小时,触发角减小,输出电压升高;阻值增大时,触发角增大,输出电压降低。Multisim仿真展示了不同电位器档位下的波形特征:0%档位时全导通,50%档位时半导通,100%档位时基本关断。该电路结构简单、调节平滑,广泛应用于调光、调速等场合,但会产生谐波干扰。

XU157303764的博客 843

巨页的配置和修改

巨页 背景知识 Linux中把页面作为管理内存的基本单位,一个页面为4KB。如果一个程序在运行过程中会用到很多的内存,那么必然会导致很多的TLB未命中和缺页异常的情况,因为一个页最大只能是4KB所以也就造成了这种问题的发生。如果直接修改默认的页面大小,那么又容易造成内存浪费,显然是不可取的。Linux引入了巨页(Huge page)的概念。允许一个页面的大小超过4KB,默认为2MB。 说到这里其实你也应该知道为什么默认为2MB了。 Linux的采取4级页表管理虚拟地址到物理地址的转换,32位系统中页表项占4

weixin_48101150的博客 4549

手把手教你用Wireshark抓包分析Profinet非周期通信(附实战案例)

本文详细解析了PROFINET非周期通信(RTA)的技术原理与实战应用,通过Wireshark抓包分析,揭示从PLC请求到驱动器响应的完整对话过程。涵盖实验环境搭建、关键配置步骤、典型参数访问流程及故障诊断案例,帮助工程师深入理解并优化工业网络通信性能。

Black的专栏 1050

001、Zephyr RTOS简介与历史背景

本文介绍了Zephyr RTOS的特点及其在嵌入式开发中的应用。作者通过亲身经历比较了Zephyr与传统RTOS的差异,重点分析了Zephyr的设备树、统一驱动模型、基于CMake的构建系统、POSIX兼容层等核心特性。文章详细阐述了Zephyr在内核设计上的优势,如中断处理模型、内存管理等,并提供了社区生态和使用建议。作者建议开发者从简单项目入手逐步掌握Zephyr,同时指出了常见的使用问题和适用场景,认为Zephyr特别适合复杂软件架构的物联网和工业控制项目。

m0_50546716的博客 155

linux 内核巨页和透明大页

一. 巨页 的使用场景 在 Linux 操作系统上运行内存需求量较大的应用程序时,由于其采用的默认页面大小为 4KB,因而将会产生较多 TLB Miss 和缺页中断,从而大大影响应用程序的性能。当操作系统以 2MB 甚至更大作为分页的单位时,将会大大减少 TLB Miss 和缺页中断的数量,显著提高应用程序的性能。这也正是 Linux 内核引入大页面支持的直接原因。好处是很明显的,假设应用程序需要 2MB 的内存,如果操作系统以 4KB 作为分页的单位,则需要 512 个页面,进而在 TL...

qqxlt的博客 711

从零开始跑通3DGS教程:(三)坐标系与尺度编辑(CloudCompare)

本文所属《从零开始跑通3DGS教程》系列文章; sfm重建的点云已经丢掉了尺度信息,并且坐标系跟图像数据有关(SFM初始化选择的图像),所以如果想恢复物理真实尺度,以及在想要的视角下渲染,那么需要对尺度和坐标系进行编辑修正,下文介绍如何使用CloudCompare修改坐标系和尺度

诺有缸的高飞鸟的博客 2871

数据库修仙秘境篇五——linux巨页内存编程

linux大页内存 HugePages是通过使用大页内存来取代传统的4kb内存页面,使得管理虚拟地址数变少,加快了从虚拟地址到物理地址的映射以及通过摒弃内存页面的换入换出以提高内存的整体性能。 概念 Page Table: page table也就是一种用于内存管理的实现方式,用于物理地址到虚拟之间的映射。因此对于内存的访问,先是访问Page Table,然后根据Page Table 中的映射关系,隐式的转移到物理地址来存取数据。 TLB: Translation Lookaside Buffer (TL

growdu的网络博客 1958

cadence17.4和16.6同时安装无法使用的问题

经过对报错的问题分析,发现还是17.4的lic文件和16.6的不一样,16.6的版本总是无法找到自己对应的lic文件。卸载了,重新单独安装16.6,这里就是正确的。包括使用这些工具去修复这些问题,都无法接近。已经放弃了,使用哪个版本就安装 哪个版本。这个也无法解决问题。

D_Katter的博客 2326

华为OD机试真题 新系统 2026-04-22 Java&Go 实现【小学生班长选举增强版】

9 月份开学第一天,小学某班级进行班长选举活动,班级共有 N 个学生,每个学生最多可投 3 票(对同一个人只能投一票),也可以弃权不投票,大家投票时写上对应学生的名字。 假设学生不存在重名。考虑到部分少数民族名字带分隔,且整体较长,同学在投票时为了方便,允许同学写全称,也可以只写其中的部分连续段。 例如班级里只有 2 个少数民族名称带点的同学:

MISAYAONE的博客 263

Hugepage巨页

巨页(Hugepage)是一种内存管理机制,它允许应用程序使用大于常规页大小(4KB)的内存页。使用巨页可以减少页表项的数量,从而降低内存管理开销,提高TLB(转换后备缓冲区)命中率,加速内存访问。DPDK充分利用了巨页技术来优化内存管理,提高数据包处理性能。减少页表项数量,降低内存管理开销。提高TLB命中率,加速虚拟地址到物理地址的转换。减少页面错误发生,提高内存访问效率。利用连续的物理内存,提高缓存利用率和内存访问性能。

weixin_41578517的博客 1141

华为OD机试真题2026双机位C卷 Python&JS 语言 实现【主次关联成环警告】

在ICT运维领域,现网运维工程师面向对设备上报的众多告警,往往需要筛选出最主要的告警优先处理,次等级的告警或许为同一个根因导致的告警,处理优先级会放后或者不处理,这样就诞生出主次关联告警的概念。给定一系列告警的主次关联关系,判断是否存在如下情况:

MISAYAONE的博客 269

深入学习Linux内核页框回收

目录 算法 1.选择目标页 2.PFRA设计 3.反向映射 3.1.匿名页的反向映射 3.2.try_to_unmap_anon()函数 3.3.try_to_unmap_one()函数 映射页的反向映射 优先搜索树 try_to_unmap_file()函数 PFRA实现 最近最少使用(LRU)链表 在LRU链表之间移动页 mark_page_accessed()函数 page_referenced()函数 refill_inactive_zone()函数 内存紧缺回

charlie114514191的博客 1406

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ubuntu 禁用透明大页_如何在Docker容器中使用巨页(大页)

在linux环境下常规页面大小是4K,常规巨页大小有两种一种是2MB,一种是1GB。巨页的好处是:减少硬件tlb miss,如此在连续内存访问场景下可以得到较大的性能提升。一般在数据库如:postgreSQL,mySql等数据库都有使用巨页时的优化措施。本文将详细介绍如何在容器环境下使用巨页,以及如何对容器使用的巨页进行限制。当前centos 7.5为止,透明巨页不支持1GB,只支持4k—>...

weixin_35881620的博客 876

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux内核:Gigantic巨页与CMA的结合的PATCH补丁提交

目录 概述 完整的PATCH 推荐阅读 概述 Facebook的Roman Gushcin发送的这个patch把Gigantic巨页(SIZE:1GB)与CMA进行了一个完美的结合: https://lkml.org/lkml/2020/3/9/1135 CMA有利于在开机的时候就预留一大片内存,但是这片内存如果不被cma_alloc()申请走,则可被movable的页面复用,并不会造成直接的浪费。 而Linux的Gigantic hugepage则要求能够在运行时通过 echo .

RToax 991

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Linux内核学习路线 学习linux内核的建议

学习linux内核,这个可不像学一门语言,c或者java一个月或者3月你就能精通掌握。学习linux内核是需要一步一步循序渐进,掌握正确的linux内核学习路线对学习至关重要,本篇文章就来分享学习linux内核的一些建议吧。 1. 了解操作系统基本概念。如果不会,可以学习《操作系统:设计与实现》Andrew S.Tanenbaum 写的那本。以MINIX为例子讲解操作系统的概念。非常推荐。 2...

Areigninhell的博客 8688

Linux 内存巨页与透明巨页学习

Huge Pages(静态巨页):静态巨页,就是系统启动时就预先分配好、数量固定、位置固定、不会被内核动的大页内存。通过大幅减少页表数量、提高 TLB 命中率,显著降低 CPU 地址翻译负担。Transparent Huge Pages (透明巨页)THP 透明巨页是内核自动把 4KB 页合并成 2MB 巨页的机制,合并时会卡顿,对应用透明。优点是自动优化、无需配置;缺点是会造成内存紧缩、CPU 毛刺、IO 波动。

qq_50247813的博客 486

Linux内核页回收

页回收

weixin_49382066的博客 2047

linux 内核 大页与小页

linux 内核 大页与小页

tangzhangyin的专栏 1327

linux内存管理 巨页使用测试以及勘误

begin pid=30371,execname=main.o,f_op=hugetlbfs_file_operations,read=hugetlbfs_read,aio=0,没错,就是hugetlbfs_read。.read = hugetlbfs_read,--------------------------------初始化了。查看vfs_read代码,要确定下是否hugetlbfs_read就是file->f_op->read。然后gdb跟踪如下,发现是可以读的,读出来数据也是正常的。

m0_74282605的博客 176
上一篇: 内核与用户态程序共享内存的方法
下一篇: virtio驱动学习笔记
无忧老猪
博客等级 码龄18年 200粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值