Linux内核中常见内存分配函数详解

1. kmalloc()kmalloc() 是 Linux 内核提供给开发者使用最多并且最为基础的一种动态申请连续物理空间方法。

在Linux内核中,内存管理是一个非常重要的子系统。它负责管理系统中所有的物理和虚拟内存,以便于操作系统能够高效地使用可用的资源。其中,最为基础也是最为重要的一部分就是内存分配。

在本文中,我们将会介绍一些在Linux内核中常见的内存分配函数,并且深入探讨它们各自所使用到的算法、数据结构以及优劣势。

1. kmalloc()

kmalloc() 是 Linux 内核提供给开发者使用最多并且最为基础的一种动态申请连续物理空间方法。它可以用来申请小于 128KB 的连续空间,并且通常被用于申请较小块大小(如:网络设备驱动程序缓冲区、进程栈等)。

kmalloc() 函数调用时需要传递两个参数:所需空间大小和 GFP_XXX 标志位(GFP 表示 Get Free Pages)。这些标志位表示了该函数对应着不同类型、不同目标场景下所需要满足的具体条件及其优先级。例如:

– GFP_KERNEL :表示该请求只能阻塞当前进程;

– GFP_ATOMIC :表示该请求必须立即成功,不允许阻塞当前进程;

– GFP_DMA :表示该请求需要申请的内存物理地址必须小于 16MB。

kmalloc() 函数的实现是基于 slab 分配器。slab 分配器首先会从 slab 高速缓存中获取一个 slab(即一块连续的物理内存区域),然后在此基础上分配所需大小的内存空间。如果高速缓存中没有可用的 slab,则会尝试从页分配器那里获取新的空间。

2. vmalloc()

vmalloc() 是 Linux 内核提供给开发者使用最多并且最为基础的一种动态申请非连续虚拟空间方法。它可以用来申请大于 128KB 的非连续空间,并且通常被用于申请较大块大小(如:设备驱动程序、模块代码等)。

vmalloc() 函数调用时只需要传递一个参数:所需空间大小。它会在虚拟地址空间中寻找足够大、未被占用过的连续区域,将其映射到物理地址上,并返回对应虚拟地址指针。

vmalloc() 函数实现是基于 vm_area_struct 结构体和 vma 段链表机制。当用户调用 vmalloc() 时,Linux 内核会创建一个新的 vma 结构体,并将其插入到进程的 vma 链表中。在接下来的内存分配过程中,内核会以 vma 为单位进行管理和申请。

Linux内核中常见内存分配函数详解

3. kzalloc()

kzalloc() 是 Linux 内核提供给开发者使用最多并且最为基础的一种动态申请连续物理空间方法,它与 kmalloc() 函数非常相似,但是不同之处在于 kzalloc() 会自动将分配到的内存空间清零。

kzalloc() 函数调用时需要传递两个参数:所需空间大小和 GFP_XXX 标志位(GFP 表示 Get Free Pages)。这些标志位表示了该函数对应着不同类型、不同目标场景下所需要满足的具体条件及其优先级。例如:

kzalloc() 函数实现方式与 kmalloc() 相似,都是基于 slab 分配器。它首先会从 slab 高速缓存中获取一个 slab(即一块连续的物理内存区域),然后在此基础上分配所需大小的内存空间,并将其清零。

4. kmem_cache_alloc()

kmem_cache_alloc() 是 Linux 内核提供给开发者使用的一种高效、可重用的内存分配方法。它可以用于申请小于 128KB 的连续空间,并且通常被用于申请较小块大小(如:网络设备驱动程序缓冲区、进程栈等)。

kmem_cache_alloc() 函数调用时需要传递两个参数:所需空间大小和 kmem_cache_t 对象。其中,kmem_cache_t 对象是一个描述 slab 分配器的结构体,包含了该分配器所管理的 slab 高速缓存、每个 slab 中可使用和已使用的内存块数量等信息。

在实际应用中,开发者可以先通过 kmem_cache_create() 函数创建一个新的 kmem_cache_t 对象,并指定其名称、所管理内存块大小以及其他相关属性。然后,在接下来需要分配内存空间时,直接调用 kmem_cache_alloc() 即可。

kmem_cache_alloc() 函数实现方式与 kmalloc() 相似,都是基于 slab 分配器。但是不同之处在于,在每次从高速缓存获取到新 slab 后,Linux 内核会将该 slab 的部分空间留作元数据区域(如:记录当前 slab 中已经使用过哪些位置)。

5. dma_alloc_coherent()

dma_alloc_coherent() 是 Linux 内核提供给开发者使用的一种动态申请物理内存空间方法。它可以用于申请小于 128KB 的连续物理内存,通常被用于需要进行 DMA(Direct Memory Access)操作的设备驱动程序中。

DMA 是指在不经过 CPU 参与的情况下,直接将设备的数据读取到或从内存中写入到目标位置。因此,在进行 DMA 操作时,需要确保所使用的物理内存区域不会被其他进程或线程占用,并且能够实现连续、高速地访问。

dma_alloc_coherent() 函数调用时需要传递三个参数:所需空间大小、分配内存地址和 GFP_XXX 标志位(GFP 表示 Get Free Pages)。其中,分配内存地址是一个二级指针类型,表示了该函数成功分配后返回的物理地址。

dma_alloc_coherent() 函数实现方式与 kmalloc() 和 kzalloc() 不同。它首先会从页分配器那里获取新空间,并将其映射到虚拟地址空间上。然后,在接下来进行 DMA 操作时,可以直接通过该虚拟地址指针来访问对应物理地址上的数据内容。

总结</h3