netmap分析(2)-原理分析之内存管理

本文深入探讨了Netmap高性能IO框架中的内存管理机制。重点介绍了内存池方案的设计思想及其在内核与用户空间高效交互中的作用。此外,还详细解析了内存池的初始化流程及netmap_adapter的相关操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文发表在 YYNOTE.COM, 地址 : http://yynote.com/blog/detail/networking/netmap-study-2-memory-mgt



在工作中用到netmap这个高性能IO框架,觉得不错,就整理了一些分析笔记,和大家共享,欢迎交流.

内存池方案

  Netmap为了避免内存的频繁申请和释放,采用了内存池方案。预先在内核申请一块连续的大内存用于满足netmap的各种需求。根据netmap对内存的使用,内存池分为三部分:

  • 用于分配netmap_ if 数据结构.
  • 用于分配netmap_ ring 数据结构.
  • 用于分配netmap_ slot 数据结构.

如下图所示:

netmap memory ring

  每个netmap_ if 在IF POOL 中都有一个偏移,而通过mmap 返回的地址是指向内存池开始地址,也是IF POOL 的开始地址。这样即可快速方便的在内核空间找到对应的netmap_if 结构。

  在netmap_ if / netmapring/ netmap slot中均使用了偏移加索引这种方式定位结构体实例,其原因在于避免用户空间地址和内核空间地址的转换,通过偏移加索引,外加内 存映射,用户空间即可方便的通过映射的地址访问这些内核地址空间中的数据。

  下图是整个内存池和各个相关数据结构的关系图:

内存池的初始化流程

  1. netmap_adapter 的申请

    在 e1000_ probe()->e1000_ netmap _ attach() ->netmap _ attache() 中:申请 netmap_ adapter 并且通过 WNA(ifp) = na; 保存至netdevice 的 ax25ptr 指针中。

  2. 在linux_ netmap_ open 中会申请netmap_ priv_ d 结构priv, 然后存储在 file->private_ data 域中.

  3. 在ioctl (NIOCGINFO) 中调用 至: linux_ netmap_ ioctl -> netmap_ ioctl 的Case NIOCGINFO中, 进而调用netmap_ get_ memory_ locked(priv) . 此时, priv 中的np_ ifp = NULL, 因此NA=NULL,所以: nmd = nm_mem.

  4. 接下来调用至netmap_ mem_ global_ finalize. 在该函数中先调用netmap_ memory_ config 进行参数配置,比如页对齐等,然后调用netmap_ mem_ finalize_ all , 调用 netmap_ finalize_ obj_ allocator 分配内存,设置虚拟地址和物理地址映射查找表。

    至此,设置全局配置:

    <code style="font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-size:undefined; padding:0px; color:inherit; white-space:pre-wrap; background-color:transparent"><span class="pln" style=""><span class="pln" style=""> netmap_buf_size </span></span><span class="pun" style=""><span class="pun" style="">=</span></span><span class="pln" style=""><span class="pln" style=""> nmd</span></span><span class="pun" style=""><span class="pun" style="">-></span></span><span class="pln" style=""><span class="pln" style="">pools</span></span><span class="pun" style=""><span class="pun" style="">[</span></span><span class="pln" style=""><span class="pln" style="">NETMAP_BUF_POOL</span></span><span class="pun" style=""><span class="pun" style="">].</span></span><span class="pln" style=""><span class="pln" style="">_objsize</span></span><span class="pun" style=""><span class="pun" style="">;</span></span><span class="pln" style=""><span class="pln" style=""><br style="" /> netmap_total_buffers </span></span><span class="pun" style=""><span class="pun" style="">=</span></span><span class="pln" style=""><span class="pln" style=""> nmd</span></span><span class="pun" style=""><span class="pun" style="">-></span></span><span class="pln" style=""><span class="pln" style="">pools</span></span><span class="pun" style=""><span class="pun" style="">[</span></span><span class="pln" style=""><span class="pln" style="">NETMAP_BUF_POOL</span></span><span class="pun" style=""><span class="pun" style="">].</span></span><span class="pln" style=""><span class="pln" style="">objtotal</span></span><span class="pun" style=""><span class="pun" style="">;</span></span><span class="pln" style=""><span class="pln" style=""><br style="" /><br style="" /><br style="" /> netmap_buffer_lut </span></span><span class="pun" style=""><span class="pun" style="">=</span></span><span class="pln" style=""><span class="pln" style=""> nmd</span></span><span class="pun" style=""><span class="pun" style="">-></span></span><span class="pln" style=""><span class="pln" style="">pools</span></span><span class="pun" style=""><span class="pun" style="">[</span></span><span class="pln" style=""><span class="pln" style="">NETMAP_BUF_POOL</span></span><span class="pun" style=""><span class="pun" style="">].</span></span><span class="pln" style=""><span class="pln" style="">lut</span></span><span class="pun" style=""><span class="pun" style="">;</span></span><span class="pln" style=""><span class="pln" style=""><br style="" /> netmap_buffer_base </span></span><span class="pun" style=""><span class="pun" style="">=</span></span><span class="pln" style=""><span class="pln" style=""> nmd</span></span><span class="pun" style=""><span class="pun" style="">-></span></span><span class="pln" style=""><span class="pln" style="">pools</span></span><span class="pun" style=""><span class="pun" style="">[</span></span><span class="pln" style=""><span class="pln" style="">NETMAP_BUF_POOL</span></span><span class="pun" style=""><span class="pun" style="">].</span></span><span class="pln" style=""><span class="pln" style="">lut</span></span><span class="pun" style=""><span class="pun" style="">[</span></span><span class="lit" style=""><span class="lit" style="">0</span></span><span class="pun" style=""><span class="pun" style="">].</span></span><span class="pln" style=""><span class="pln" style="">vaddr</span></span><span class="pun" style=""><span class="pun" style="">;</span></span><span class="pln" style=""><span class="pln" style=""><br style="" /></span></span></code>
  5. 接下来在 ioctl (NIOCREGIF) 中通过 get_ ifp 获取到 net_ device 的ifp , 然后在netmap_ do_ regif 中, priv->np_ ifp = ifp; 将当前的net_ device 保存至 file->private->np_ ifp. 同时此时 通过 ifp 指针能够获取到保存在其中的 netmap_ adapter 结构. 
      

  6. 接下来是通过 netmap_ if_ new 调用 netmap_ mem_ if_ new 分配netmap_ adapter的 netmap_ ring 管理结构体, 调用netmap_ new_ bufs 给每个ring的每个slot向netmap缓存区申请内存.


今天就写到这了.


文章版权归属yynote.com.转载请标明出处.

本文地址: http://yynote.com/blog/detail/networking/netmap-study-2-memory-mgt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值