我想编写一个内核模块,我将获得接近8 mbps的TCP / IP数据包。我必须将这些数据包存储500毫秒。稍后这些数据包应按顺序转发。这些应该为30个成员完成。应该采用哪种最佳方法?我应该kmalloc
一次使用(kmalloc(64000000, GFP_ATOMIC)
吗?因为如果我kmalloc
和kfree
,每次都会花费时间,从而导致性能问题。另外,如果我一次性在内核中分配内存,linux内核会允许我这样做吗?
答案 0 :(得分:4)
我曾经在10Gbs链接上编写了一个处理数据包的内核模块。我使用vmalloc
分配大约1GB的连续(虚拟)内存来将静态大小的哈希表放入其中以执行连接跟踪(code)。
如果您知道需要多少内存,我建议您预先分配它。这有两个好处
kmalloc(_, GFP_ATOMIC)
无法让你记忆,你不必考虑策略。这实际上经常在重负荷下发生。缺点
因此,对于编写专用内核模块,请预先分配尽可能多的内存;)
如果为许多新手用户使用的商用硬件编写内核模块,那么按需分配内存(浪费更少的内存)会很不错。
你在哪里分配内存? GFP_ATOMIC
只能返回非常少量的内存,只有在内存分配无法休眠时才能使用。您可以在安全睡眠时使用GFP_KERNEL
,例如,不在中断环境中。有关详情,请参阅this question。在模块初始化期间使用vmalloc
来预先分配所有内存是安全的。
答案 1 :(得分:0)
由于vmalloc
,使用corny(answer)时,像Linux kernel 5.2的released Q3 2019中使用kernel changes会更快。>
Linux内核的
vmalloc
代码具有在Linux 5.2上执行更快的潜力,尤其是在嵌入式设备上。
Vmalloc用于在虚拟地址空间中分配连续的内存,并且在Linux 5.2合并窗口的预期最后一天今天进行了很好的优化合并。几分钟前,与 Andrew Morton 合并的pull (commit cb6f873)的一部分是“对vmalloc进行了很大的更改,从而带来了巨大的性能优势。”
对vmalloc代码的主要更改是跟踪要分配的空闲块。
当前,新的VA区域的分配是通过繁忙列表迭代完成的,直到在两个繁忙区域之间找到合适的空洞为止。因此,每个新分配都会导致列表增长。由于清单较长且允许的参数不同,因此在嵌入式设备上进行分配可能需要很长时间(毫秒)。此修补程序将vmalloc内存布局组织到
VMALLOC_START
-VMALLOC_END
范围的空闲区域中。它使用一棵红黑树,使按偏移量对块进行排序,并与链表配对,从而按地址递增的顺序保留可用空间。使用 Uladzislau Rezki 中的补丁,与Linux 5.1及更低版本上的行为相比,调用
vmalloc()
最多可以节省67%的时间,至少是由开发人员在QEMU。
提交,如mirrored on GitHub, is here:
/*
* This augment red-black tree represents the free vmap space.
* All vmap_area objects in this tree are sorted by va->va_start
* address. It is used for allocation and merging when a vmap
* object is released.
*
* Each vmap_area node contains a maximum available free block
* of its sub-tree, right or left. Therefore it is possible to
* find a lowest match of free area.
*/
使用the function:
/*
* Merge de-allocated chunk of VA memory with previous
* and next free blocks. If coalesce is not done a new
* free area is inserted. If VA has been merged, it is
* freed.
*/
static __always_inline void
merge_or_add_vmap_area(struct vmap_area *va,
struct rb_root *root, struct list_head *head)
/*
* Find a place in the tree where VA potentially will be
* inserted, unless it is merged with its sibling/siblings.
*/
/*
* Get next node of VA to check if merging can be done.
*/
/*
* start end
* | |
* |<------VA------>|<-----Next----->|
* | |
* start end
*/
...
/*
* start end
* | |
* |<-----Prev----->|<------VA------>|
* | |
* start end
*/