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;
}