注意,这里的PAGE_OFFSET指的就是3G(针对x86位系统).
与页面分配系函数一样, _kmalloc_函数申请的内存也处于物理内存映射区域,在物理上是连续的。 _Kmalloc_函数是slab分配器提供的分配内存的接口,slab是什么?这里不去具体讲slab分配原理,想详细了解的slab可以参考这里. 简单说明一下:slab是为了避免内部碎片使得一个页面内包含的众多小块内存可独立被分配使用,是为分配小内存提供的一种高效机制。追踪kmalloc函数,可以发现,它最终还是调用前面提到的
__ _alloc_pages()_函数。既然 _kmalloc_基于slab实现,而slab分配机制又不是独立的,本身也是在以页面为单位分配的基础上来划分更细粒度的内存供调用者使用。就是说系统先用页分配器分配以页为最小单位的连续物理地 址,然后 _kmalloc_再在这上面根据调用者的需要进行切分。
既然slab是为了解决内部碎片的问题,那想必也有一个解决外部碎片的机制(注:外部分片是指系统虽有足够的内存,但却是分散的碎片,无法满足对大块”连续内存”的需求)。没错,伙伴关系系统就是这么一个机制。伙伴关系系统提供 _vmalloc_来分配非连续内存,其分配的地址限于上述说的 _vmalloc_start~vmalloc_end_之间。这些虚拟地址与物理内存没有简单的位移关系,必须通过内核页表才可转换为物理地址或物理页。它们有可能尚未被映射,在发生缺页时才真正分配物理页面。
说到这里,还有一个关键函数没提, kmem_cache_alloc。 kmem_cache_alloc_也是基于slab分配器的一种内存分配方式,适用于反复分配同一大小内存块的场合。首先用 _kmem_cache_create_创建一个高速缓存区域,然后用 _kmem_cache_alloc_从该高速缓存区域获取新的内存块。 _kmem_cache_alloc_分配固定大小的内存块。 _kmalloc_则是在 _kmem_cache_create_的基础实现的,其分配动态大小的内存块,查看源码可以发现 _kmalloc_函数中会有一段代码块转向调用 _kmem_cache_alloc:
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size)) {
int i = 0;
#define CACHE(x) \
if (size
Original: https://www.cnblogs.com/alantu2018/p/9177356.html
Author: AlanTu
Title: 深入理解Linux内存分配
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/23025/
转载文章受原作者版权保护。转载请注明原作者出处!