3. API函数
现在来创建slab、向allocator增加内存页、回收内存页的应用程序接口【API接口】以及slab对对象的进行分配和销毁的操作
3.1创建并初始化slab分配器allocator:
static inline guint
allocator_categorize (gsize aligned_chunk_size)
{
/* speed up the likely path */
if (G_LIKELY (aligned_chunk_size && aligned_chunk_size <= allocator->max_slab_chunk_size_for_magazine_cache))
return 1; /* use magazine cache */会发现宏G_LIKELY其实是利用了__builtin_expect的属性,具体作用可以看我先前写的
/* the above will fail (max_slab_chunk_size_for_magazine_cache == 0) if the
* allocator is still uninitialized, or if we are not configured to use the
* magazine cache.
*/
if (!sys_page_size)
g_slice_init_nomessage ();//先是通过slice_config_init初始化slice_config,而后初始化allocator
if (!allocator->config.always_malloc &&
aligned_chunk_size &&
aligned_chunk_size <= MAX_SLAB_CHUNK_SIZE (allocator))//注意这三个条件
{
if (allocator->config.bypass_magazines)
return 2; /* use slab allocator, see [2] */使用slab分配内存
return 1; /* use magazine cache */
}
return 0; /* use malloc() */
}
从以上的代码可知,这一过程极其的简单!它主要做了三样事情:一是获得系统页面大小sys_page_size;二是初始化config,以此决定了allocator分配器使用的分配机制;三是建立了SlabInfo指针数组。
3.2 从allocator获取chunk_size大小内存块的起始地址
函数 g_slice_alloc是提供给外部的API函数,它担当起初始化并返回所需内存空间的大小的其实地址
gpointer
g_slice_alloc (gsize mem_size)
{
gsize chunk_size;
gpointer mem;
guint acat;
chunk_size = P2ALIGN (mem_size);//对mem_size进行8自己对齐
acat = allocator_categorize (chunk_size); //创建并初始化allocator,上面有讲解
if (G_LIKELY (acat == 1)) /* allocate through magazine layer */
{
ThreadMemory *tmem = thread_memory_from_self();
guint ix = SLAB_INDEX (allocator, chunk_size);
if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
{
thread_memory_swap_magazines (tmem, ix);
if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
thread_memory_magazine1_reload (tmem, ix);
}
mem = thread_memory_magazine1_alloc (tmem, ix);
}
else if (acat == 2) /* allocate through slab allocator */采用slab分配方式
{
g_mutex_lock (allocator->slab_mutex);
mem = slab_allocator_alloc_chunk (chunk_size);//slab分配的主要函数
g_mutex_unlock (allocator->slab_mutex);
}
else /* delegate to system malloc */
mem = g_malloc (mem_size);
if (G_UNLIKELY (allocator->config.debug_blocks))
smc_notify_alloc (mem, mem_size);
return mem;
}