- 对于小的对象使用SLUB分配器进行分配
- kmem_cache 作为对象分配的缓存区(每次分配对象的时候都先到缓存区找空闲的区域)
struct kmem_cache { struct kmem_cache_cpu __percpu *cpu_slab; /* Used for retriving partial slabs etc */ unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ int object_size; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ #ifdef CONFIG_SLUB_CPU_PARTIAL int cpu_partial; /* Number of per cpu partial objects to keep around */ #endif struct kmem_cache_order_objects oo; /* Allocation and freeing of slabs */ struct kmem_cache_order_objects max; struct kmem_cache_order_objects min; gfp_t allocflags; /* gfp flags to use on each alloc */ int refcount; /* Refcount for slab cache destroy */ void (*ctor)(void *); ...... const char *name; /* Name (only for display!) */ struct list_head list; /* List of slab caches */ ...... struct kmem_cache_node *node[MAX_NUMNODES]; };
- kmem_cache_order_object 缓存就是由分配了几页大内存块(Max,min)。
结构如图
image.png
- kmem_cache_cup 和 kmem_cache_node 第一个为快速通道fastpath,第二个为普通通道 slowpath
结构如图
image.png
page 主页,partial 已经部分使用的页。
struct kmem_cache_cpu { void **freelist; /* Pointer to next available object */ unsigned long tid; /* Globally unique transaction id */ struct page *page; /* The slab from which we are allocating */ #ifdef CONFIG_SLUB_CPU_PARTIAL struct page *partial; /* Partially allocated frozen slabs */ #endif ...... };
freelist 指向第一个空闲的对像,page指向当前页,partial 执行其他部分使用的页
- 分配内存流程
- 从快速通道kmem_cache_cpu 的 freelist中寻找,假如有直接返回
- 从kmem_caceh_cpu 中取出一块内存页,将当前page指针指向这个页,重现设置freelist。
- 假如上述没有则到 kmem_cache_node 的partial 中取出一块可用的内存块,并重新设置freelist
- 还没有的话调用 alloc_slab_page 进行内存分配
- 内存换出
- 被动换出
- get_page_from_freelist>node_reclaim>shrink_node
- 主动换出
- 内核线程 kswapd 但内存紧张就会检查
- balance_pgdat>kswapd_shrink_node>shrink_node
- 被动换出
- shrink_node 函数
- 内存页分为两种,匿名页(和虚拟内存空间关联)和内存映射
- 上述两种内存都维护一个两个LRU列表,active 和 inactive
- 每次调用这个函数都会查找 inactive 的最少使用内存页换出
总结
image.png
网友评论