• dpdk 内存管理 原理剖析


    dpdk 的内存管理层次结构

    • 物理巨页的管理
    • 虚拟地址空间的管理
    • heap管理(变长buffer)
    • mempool管理(定长buffer)
      在这里插入图片描述

    物理巨页的管理

    dpdk中通过 数组 hugepg_tbl[LEN] 组织所有的巨页。巨页管理的主要需求是:

    • 在用户空间 获取物理巨页
    • 规则化 虚拟地址 与 物理巨页的映射 关系。
      • 约束1:保证 连续的va对应连续的pa
      • 约束2:不连续的va则pa不连续。

    约束1 可以方便用户态网卡驱动进行dma映射。dma映射要求 网卡视角的物理地址是连续的。
    约束2 方便heap堆管理的rte_free() 进行合并,同时保持约束1成立。即两块连续的{va, len}可以合并,合并后其对应 物理地址区域 也应该是连续的。

    物理巨页的获取 - 第一次mmap()

    在用户空间,我们如何申请利用巨页呢? 通过在 hugetblfs文件系统类型的 /dev/hugepages 先创建文件/dev/hugepages/rte_hugepage_%d,然后 mmap()系统调用 获取1G的巨页。有别于普通文件系统的内存申请,这里无需设置文件大小,如ftruncate(fd)
    但此时的物理巨页的位置 是用户无法控制的,需后续进一步的排序处理。

    // lib/eal/linux/eal_memory.c
    map_all_hugepages()
    	// 拼接文件名 /dev/hugepages/rte_hugepage_%s
    	eal_get_hugefile_path(hf->filepath, sizeof(hf->filepath),
    				hpi->hugedir, hf->file_id);
    	// 在/dev/hugepages/ 目录下 新建文件
    	fd = open(hf->filepath, O_CREAT | O_RDWR, 0600);
    	// 获取物理巨页。注意:多次mmap(),该文件仍 只有1g大小
    	virtaddr = mmap(NULL, hugepage_sz, PROT_READ | PROT_WRITE,
    			MAP_SHARED | MAP_POPULATE, fd, 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    物理巨页的排序 - 第二次mmap()

    由上小节可知,用户通过mmap()系统调用获取的物理巨页的位置是不可控的,该现象可由用户 通过读写 /proc/self/pagemaps 来查看当前进程的va所对应的pa。依靠/proc/self/pagemaps获取的pa信息,进行排序,然后通过mmap() 重新分配 递增的va给排序后的 物理巨页。同时,连续的物理巨页,其va也是连续的。

    // 涉及函数
    
    
    • 1
    • 2

    在这里插入图片描述
    在这里插入图片描述

    虚拟地址空间的管理

    当用户需要 一片虚拟地址区域时,可通过eal_get_virtual_area() 进行获取,其从管理的va空闲区域头部获取 虚拟地址区域。dpdk 会让 虚拟地址区域 连续。

    heap(变长buffer) 的管理

    这部分的实现 遵循 常见的变长buffer管理方式,即将 不同长度的空闲区域 通过 链表组织。在连续的物理巨页 头部添加 malloc_elem结构,进行管理。

    mempool管理(定长buffer)

    在heap的基础上,dpdk针对定长buffer的管理 进行优化。步骤如下:

    1. 先在heap中malloc一个 定长buffer的大数组。
    2. 将 空闲的定长元素 的指针 加入 rte_ring进行管理。

    其主要优点是,rte_ring无锁队列,通过原子操作,可减低 malloc的锁争用开销,且引入per-cpu 栈buffer cache的快分配流程。

    总体视角

    主要数据结构的关联图

    在这里插入图片描述

    数据结构 通过文件共享

    dpdk 多进程模式下,进程间通过 文件来共享文件,通过文件锁来同步。
    已知的 文件 与 数据的映射如下:

    /var/run/dpdk/rte/hugepage_data  =>  hugepage_file []
    /dev/hugepage/rte_hugepage_0     => huge page
    /var/run/dpdk/rte/fbarray_0      => rte_fbarray->data
    /var/run/dpdk/rte/fbarray_memzone
    /var/run/dpdk/rte/config         => rte_mem_config
    
    • 1
    • 2
    • 3
    • 4
    • 5

    附录

    https://upload-images.jianshu.io/upload_images/8087815-492c366e5f913d4c.png

  • 相关阅读:
    基于微信小程序的电影院票务系统设计与实现-计算机毕业设计源码+LW文档
    Go 结合Gin导出Mysql数据到Excel表格
    【百战GAN】定制属于二次元宅们的专属动漫头像,这款GAN正好!
    serial库常见用法
    算法金 | 不愧是腾讯,问基础巨细节 。。。
    4_Git
    python中的进程与线程,使用.multiprocessing
    ACTF 2022圆满落幕,0ops战队二连冠!!
    linux之ldconfig命令的作用
    【Python】从同步到异步多核:测试桩性能优化,加速应用的开发和验证
  • 原文地址:https://blog.csdn.net/qq_20679687/article/details/126570185