Linux 内存管理: Kmalloc

这里只说物理内存管理 linux内核的,看了很多讲解的内存的东西,但是自己总结的时候总感觉无从下手,这里就从实际物理内存分配接口开始吧。

Kmalloc 它分配连续的物理内存空间 ,它不负责把分配的内存空间清零,它能分配多大的呢?并且它只能分配ZONE_NORMAL的不能分配dma和high里的,也就是只分配低端内存.一般情况下内存被分为三个zone:NORMAL、DMA、HIGH.

这个函数是建立在slab分配器的基础上的,通过cache 而cache有通过slab 分配obj 。

在开始分析kmalloc函数之前,我们需要说明一下linux内核物理内存的分配函数API:

__get_free_pages它会调用alloc_pages,它的特点是不能从HIGHMEM分配内存,分配2的幂个连续物理页面。它有简化模式(只分配一page)
__get_free_page,而get_zeroed_page接口分配的页面内容对应填充为0. 从dma分配可以调用__get_dma_pages(它本质也是调用__get_free_pages)

那么终极接口alloc_pages它可以从任何zone里申请内存,当然前提设置对应的flags.

参考内核:linux3.18.13
参考书籍:《linux内核设计与实现》《linux设备驱动程序》《深入理解linux设备驱动内核机制》

下面我们就说说kmalloc:(关于分配时候的flags这里不讨论,具体可以参考资料)

我们先看头文件
#include
而关于它的具体实现我们看slab.h中

一般系统默认#include

这里可以补充下代码关于kmalloc_sizes.h

我们看到函数开头需要说明一下:
__builtin_constant_p 是编译器gcc内置函数,用于判断一个值是否为编译时常量,如果是常数,函数返回1 ,否则返回0。此内置函数的典型用法是在宏中用于手动编译时优化显然如果size为常数 则用__kmalloc(size, flags);申请内存.

它查询需要分配的内存在哪个系统cache然后调用

我们看具体代码:

它实际的分配是slab_alloc:

 

它调用objp = __do_cache_alloc(cachep, flags); 除了检查一些标志等继续调用
____cache_alloc(cachep, flags);

它是一个统一的接口 (有检测numa和uma ,linux默认是uma 除非指定了numa)

这里我们假定是第一次使用分配内存,那么根据在kmem_cache_init中的malloc_sizes[]的初始化,在kmalloc的时候返回的kmalloc_cache指针指向的cache中用到这样个函数:

我们知道不论array被赋了什么值,最后都要初始化avail等值.

所以如果array不可用,那么就会调用;当然如果array可用那么直接返回申请的obj的内存指针.

由于第一次使用nodelist上slab链表都为空,所以must_grow

它调用cache_grow,这个函数首先计算了slab着色处理。然后调用kmem_getpages申请page,大小根据cache->gfporder,它返回申请pages的虚拟地址.

而关于slab着色跟硬件缓冲有关,为了尽量避免缓存冲突不命中问题,提高效率(cache_line问题)。可以参考《深入理解计算机系统》。

具体操作见:

我们看看另外一个很重要的操作:

1 5 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部