内存池方案
Netmap为了避免内存的频繁申请和释放,采用了内存池方案。预先在内核申请一块连续的大内存用于满足netmap的各种需求。根据netmap对内存的使用,内存池分为三部分:
- 用于分配netmap_ if 数据结构.
- 用于分配netmap_ ring 数据结构.
- 用于分配netmap_ slot 数据结构.
如下图所示:
每个netmap_ if 在IF POOL 中都有一个偏移,而通过mmap 返回的地址是指向内存池开始地址,也是IF POOL 的开始地址。这样即可快速方便的在内核空间找到对应的netmap_if 结构。
在netmap_ if / netmapring/ netmap slot中均使用了偏移加索引这种方式定位结构体实例,其原因在于避免用户空间地址和内核空间地址的转换,通过偏移加索引,外加内 存映射,用户空间即可方便的通过映射的地址访问这些内核地址空间中的数据。
下图是整个内存池和各个相关数据结构的关系图:
内存池的初始化流程
-
netmap_adapter 的申请
在 e1000_ probe()->e1000_ netmap _ attach() ->netmap _ attache() 中:申请 netmap_ adapter 并且通过 WNA(ifp) = na; 保存至netdevice 的 ax25ptr 指针中。
-
在linux_ netmap_ open 中会申请netmap_ priv_ d 结构priv, 然后存储在 file->private_ data 域中.
-
在ioctl (NIOCGINFO) 中调用 至: linux_ netmap_ ioctl -> netmap_ ioctl 的Case NIOCGINFO中, 进而调用netmap_ get_ memory_ locked(priv) . 此时, priv 中的np_ ifp = NULL, 因此NA=NULL,所以: nmd = nm_mem.
-
接下来调用至netmap_ mem_ global_ finalize. 在该函数中先调用netmap_ memory_ config 进行参数配置,比如页对齐等,然后调用netmap_ mem_ finalize_ all , 调用 netmap_ finalize_ obj_ allocator 分配内存,设置虚拟地址和物理地址映射查找表。
至此,设置全局配置:
netmap_buf_size = nmd->pools[NETMAP_BUF_POOL]._objsize;
netmap_total_buffers = nmd->pools[NETMAP_BUF_POOL].objtotal;
netmap_buffer_lut = nmd->pools[NETMAP_BUF_POOL].lut;
netmap_buffer_base = nmd->pools[NETMAP_BUF_POOL].lut[0].vaddr; -
接下来在 ioctl (NIOCREGIF) 中通过 get_ ifp 获取到 net_ device 的ifp , 然后在netmap_ do_ regif 中, priv->np_ ifp = ifp; 将当前的net_ device 保存至 file->private->np_ ifp. 同时此时 通过 ifp 指针能够获取到保存在其中的 netmap_ adapter 结构.
-
接下来是通过 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