歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Uclibc中的malloc機制分析

Uclibc是嵌入式linux系統裡面使用最多的c lib庫。最近在學習linux內核內存管理方面的東西,學完之後一直對用戶空間的內存管理很迷糊,特找了libc中的malloc部份代碼研究了一下,小有心得。特總結成此文。

本文檔結構:

一:准備知識

二:堆空間的管理結構

三:堆空間的初始化

四:FA結構的操作

五:malloc的實現

六:free的實現

七:總結

一: 准備知識:

用戶空間中,經常會調用malloc 與 free進行內存管理,它是在進程的堆空間中分配內存。如下圖所示:
 


 

二:堆空間的管理結構:

堆空間表示的數據結構

struct heap

{

//堆空間空閒區的表示結構

struct heap_free_area *free_areas;

//用於在多線程環境中加鎖保護

#ifdef HEAP_USE_LOCKING

pthread_mutex_t lock;

#endif

};

heap_free_area結構在代碼被代碼作者稱之為FA結構。它的定義如下:

struct heap_free_area

{

//空閒區的大小

size_t size;

//用於構造循環鏈表

struct heap_free_area *next, *prev;

};

注意:在FA結構裡並沒有定義指向空閒區的指針,這是因為FA結構正好放在空閒區的後面。
 

三:堆空間的初始化:

全局變量__malloc_heap表示了整個堆棧空間。它的初始化過程如下示:

struct heap __malloc_heap = HEAP_INIT_WITH_FA (initial_fa);

HEAP_INIT_WITH_FA的定義如下:

#ifdef HEAP_USE_LOCKING

# define HEAP_INIT { 0, PTHREAD_MUTEX_INITIALIZER }

# define HEAP_INIT_WITH_FA(fa) { &fa._fa, PTHREAD_MUTEX_INITIALIZER }

#else

# define HEAP_INIT { 0 }

# define HEAP_INIT_WITH_FA(fa) { &fa._fa }

#endif

變量initial_fa初始化如下:

HEAP_DECLARE_STATIC_FREE_AREA (initial_fa, 256);

#define HEAP_DECLARE_STATIC_FREE_AREA(name, size) \



static struct \

{ \

char space[(size) - sizeof (struct heap_free_area)]; \

struct heap_free_area _fa; \

} name = { "", { (size), 0, 0 } }



如此可以看出初始化的堆空間為256個字節。從上面的初始化也可以看到,在FA結構的前面靜態定義了一個數組空間。這也印證了上面說的“FA結構正好放在空閒區的後面”



四:FA結構的操作:

1:#define HEAP_FREE_AREA_SIZE(fa) ((fa)->size)

FA所代表的空閒區大小,此大小已經包含FA本身占的空間

2: #define HEAP_FREE_AREA_START(fa) ((void *)((char *)(fa + 1) - (fa)->size))

FA所代表空閒區的起始位置。fa+1到達空閒區末端。指針再下移大小個單位,即為空閒區的起始位置

3:#define HEAP_FREE_AREA_END(fa) ((void *)(fa + 1))

返回FA所表示空閒區的末尾。從FA所表示的結構可看出。從FA的地址上移一個FA的大小,剛好到達空閒的末尾

4:#define HEAP_MIN_FREE_AREA_SIZE \

HEAP_ADJUST_SIZE (sizeof (struct heap_free_area) + 32)

最少的空閒區大小。空閒區最少要能存上一個heap_free_area大小,此外還要有32字節的空閒,這是從效率來考慮的。Malloc分配內存的時候,有時候它會把一個FA分為兩段。如果剩余的內存少於HEAP_MIN_FREE_AREA_SIZE.還不如全部都將內存分配出去。因為維護空閒內存需要影響效率。這從我們後面的malloc 與 free分析中可以看到

5: __heap_delete (struct heap *heap, struct heap_free_area *fa)

該函數是將fa從heap中刪除,它的實現如下:

extern inline void

__heap_delete (struct heap *heap, struct heap_free_area *fa)

{

if (fa->next)

fa->next->prev = fa->prev;

if (fa->prev)

fa->prev->next = fa->next;

else

heap->free_areas = fa->next; //如果刪除的是它的首節點

}
只是一個簡單的鏈表操作,將fa從循環鏈表中脫節。

6: __heap_link_free_area (struct heap *heap, struct heap_free_area *fa,

struct heap_free_area *prev,

struct heap_free_area *next)

從代碼注釋上看該函數是指prev 與 next 之間的Fa合並到一起。實際上它只是在prev 與next之間插入了一項而已。

實現如下:

extern inline void

__heap_link_free_area (struct heap *heap, struct heap_free_area *fa,

struct heap_free_area *prev,

struct heap_free_area *next)

{

fa->next = next;

fa->prev = prev;



if (prev)

prev->next = fa;

else

heap->free_areas = fa; //插入節點為首節點的情況

if (next)

next->prev = fa;

}

7:__heap_link_free_area_after (struct heap *heap,

struct heap_free_area *fa,

struct heap_free_area *prev)

Copyright © Linux教程網 All Rights Reserved