Linux記憶體管理之slab分配器分析 續五

2021-05-23 13:35:48 字數 2727 閱讀 1005

九:幾點補充:

1: slab

中使用的頁面都會加上「pg_slab」標誌,以跟一般的頁面區別。另外,在釋放記憶體的時候,經常需要用到從頁面到slab的對應轉換關係。那是怎樣標識的呢?

關於標誌:

注意有以下**:

static void *kmem_getpages(kmem_cache_t *cachep, int flags, int nodeid)

…… }

關於從頁面到slab的轉換:

向夥伴系統請求記憶體

static int cache_grow (kmem_cache_t * cachep, int flags)

static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)

while (--i); }

從上面的函式可以看出,pg->lru.next指向它所在的cache pg->lru.prev指向它所在slab

在**中,用slabp = get_page_slab(virt_to_page(objp))來計算物件所在的slab

get_page_slab

定義如下:

#define  get_page_slab(pg)     ((struct slab *)(pg)->lru.prev)

所以,只要直接取pg的lru.prev即可。

slab

的這部份設計很高效,很巧妙

2:在上述**中,經常用到slab_bufctl的操作,下面就來詳細分析一下:

先來看下cache中的slab大小的計算。即cache的slab_size欄位:

kmem_cache_t * kmem_cache_create (const char *name, size_t size, size_t align,

unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),

void (*dtor)(void*, kmem_cache_t *, unsigned long))

cachep->num:slab

中的object個數

從上面可以看到,slab_size已經包括了num個kmem_bufctl_t大小,也可以理解成有num個元素的kmem_bufctl_t陣列。實際上kmem_bufctl_t又被定義為:unsigned short

typedef unsigned short kmem_bufctl_t;

slab_bufctl

()用來計算kmem_bufctl_t陣列的首位址。**如下:

static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)

我們接著看一下,kmem_bufctl_t陣列如何被初始化。初始化是在新增乙個slab 的時候,看下相應的**:

static int cache_grow (kmem_cache_t * cachep, int flags)

在對每個物件初始化的時候:

static void cache_init_objs (kmem_cache_t * cachep,

struct slab * slabp, unsigned long ctor_flags)

slab_bufctl(slabp)[i-1] = bufctl_end;

slabp->free = 0; }

初始化之後,kmem_bufctl_t陣列中的值如下圖所示:

從上面的分析可以看到,

slab

中的free

欄位與kmem_bufctl_t

陣列中的值會錯開乙個值。

再來看從

slab

中分配物件的時候:

static void* cache_alloc_refill(kmem_cache_t* cachep, int flags)

…… }

釋放對像的時候:

static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)

結合上面的初始化可以看到,有這樣的乙個規律:

kmem_bufctl_t

陣列中的slabp->free項的值就是下乙個空閒對像的序號。結合這一樣就能很好的理解這一部份**了

十:kmalloc()/kfree()的實現

kmalloc/kfree

的實現其實跟上面是所討論的是一樣的,所不同的是。上面討論的是屬於專用cache,這裡所討論的普通cache.也可以這樣說:專用cache是從資料結構方面來管理記憶體的。普通cache是以大小來管理的。

我們在前面曾討論過,slab分配器按大32*(2^0),32*(2^1),32*(2^2) ….32*(2^12)大小,共劃分了13個區域。kmalloc()根據所申請的資料大小,選擇合適的cache分配記憶體

**如下示:

void * __kmalloc (size_t size, int flags)

return null; }

kfree

的實現**:

void kfree (const void *objp)

十一:總結:

slab

分配器中有很多值得仔細研讀的**。與2.4相比,2。6核心新增了兩個緩衝結構,乙個是ac,另乙個是share。有效的緩減了對夥伴系統的壓力

Linux記憶體管理之slab演算法簡述

slab 分配機制。slab 快取 linux 所使用的 slab 分配器的基礎是 jeff bonwick 為 sunos 作業系統首次引入的一種演算法。jeff 的分配器是圍繞 物件快取進行的。在核心中,會為有限的 物件集 例如 檔案描述符 和其他常見結構 分配大量記憶體。jeff 發現對核心中...

linux記憶體管理 之 slab分配器

1 頁面分配器是頁面級的記憶體分配工具,能分配2的order次冪的連續物理記憶體。linux在頁面級記憶體分配的基礎上,開發了小記憶體分配方案 slab slob slub。後兩者分別針對大型系統和嵌入式系統。2 slab分配器的思想 先利用頁面分配器分配出單個或者一組連續的物理頁面,然後在此基礎上...

Linux記憶體管理之slab分配器分析

一 準備知識 前面我們分析過了大記憶體分配的實現機制,事實上,若為小塊記憶體而請求整個頁面,這樣對於記憶體來說是一種極度的浪費。因此linux 採用了slab 來管理小塊記憶體的分配與釋放。slab 最早是由sun 的工程師提出。它的提出是基於以下因素考慮的 1 核心函式經常傾向於反覆請求相同的資料...