Linux中的slab分专有和通用两种
1)专用
void *kmem_cache_alloc(kmem_cache_t *cachep, int flags);-->static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags)
void *kmem_cache_free(kmem cache_t *cachep, void *objp);
总的cache_cache(kmem_cache_t)指向第一层slab队列
第一层的每个slab队列中的每个slab头管理一个某种对象的队列
分配思路:首先在在缓冲池分配,失败则通过kmem_cache_alloc()分配,没有载有空闲去的slab,则通过kmem_cache_grow()构造一个空闲的
==================== mm/slab.c 1291 1299 ====================
[alloc_skb()>kmem_cache_alloc()>__kmem_cache_alloc()]
1291 static inline void * __kmem_cache_alloc (kmem_cache_t *cachep, int flags)
1292 {
1293 unsigned long save_flags;
1294 void* objp;
1295
1296 kmem_cache_alloc_head(cachep, flags);
1297 try_again:
1298 local_irq_save(save_flags);
1299 #ifdef CONFIG_SMP
......
==================== mm/slab.c 1319 1325 ====================
1319 #else
1320 objp = kmem_cache_alloc_one(cachep);//核心
1321 #endif
1322 local_irq_restore(save_flags);
1323 return objp;
1324 alloc_new_slab:
1325 #ifdef CONFIG_SMP
......
==================== mm/slab.c 1328 1336 ====================
1328 #endif
1329 local_irq_restore(save_flags);
1330 if (kmem_cache_grow(cachep, flags))
该函数根据队列头的参数gfporder分配若干个连续的物理内存页面,并将这些页面构成slab,炼乳给定的队列,对参数进行了一些检查以后,就计算出下一块slab的着色区大小,然后通过kmem_getpages()分配用于具体对象缓冲区的页面,最后通过kmem_cache_slabmgmt()建立起slab的管理信息
1331 /* Someone may have stolen our objs. Doesn't matter, we'll
1332 * just come back here again.
1333 */
1334 goto try_again;
1335 return NULL;
1336 }
1251 #define kmem_cache_alloc_one(cachep) \
1252 ({ \
1253 slab_t *slabp; \
1254 \
1255 /* Get slab alloc is to come from. */ \
1256 { \
1257 struct list_head* p = cachep->firstnotfull; \
1258 if (p == &cachep->slabs) \//为空则……
1259 goto alloc_new_slab; \
1260 slabp = list_entry(p,slab_t, list); \
1261 } \
1262 kmem_cache_alloc_one_tail(cachep, slabp); \//有了则分配
1263 })
2)通用
顶层为一个结构数组,每个数组指向一个某种大小对象的slab队列
void *kmalloc(size_t size, int flags);
void kfree(const void *objp);
内核中有一个通用缓冲池cache_sizes……
kswapd通过kmem_cache_reap()回收空闲slab页面的回收
阅读(969) | 评论(0) | 转发(0) |