nginx記憶體池管理

2021-06-18 02:27:56 字數 3736 閱讀 4455

在src/core/ngx_palloc.h中定義了記憶體池相關的結構體

**記憶體相關的

//記憶體池**結構體

struct ngx_pool_cleanup_s ;

//大塊資料分配結構體

struct ngx_pool_large_s ;

//記憶體池中資料結構體

typedef struct ngx_pool_data_t;

//記憶體池管理結構體

struct ngx_pool_s ;

//其他結構體

typedef struct ngx_pool_cleanup_file_t;

乍一看這些結構體的關係有點混亂啊,別急,咱來看一段記憶體池建立的**

src/core/ngx_palloc.c檔案中

ngx_pool_t *

ngx_create_pool(size_t size, ngx_log_t *log)

p->d.last = (u_char *) p + sizeof(ngx_pool_t);

p->d.end = (u_char *) p + size;

p->d.next = null;

p->d.failed = 0;

size = size - sizeof(ngx_pool_t);

p->max = (size < ngx_max_alloc_from_pool) ? size : ngx_max_alloc_from_pool;

p->current = p;

p->chain = null;

p->large = null;

p->cleanup = null;

p->log = log;

return p;

}

建立後結果如下圖所示:

看完了建立記憶體池的**,再來看看nginx是如何從記憶體池中分配所需要的記憶體的吧,**如下:

void *

ngx_palloc(ngx_pool_t *pool, size_t size)

p = p->d.next;

} while (p);

/*如果所有的pool都沒有可供分配的size大小空間,則新建立乙個pool,並將該pool中分配空間的首位址返回。

*/ return ngx_palloc_block(pool, size);

}return ngx_palloc_large(pool, size);

}

pool是記憶體池的首位址,size是所需分配的記憶體大小。看完了**,是不是對pool與pool之間的關係比較模糊,別著急,pool與pool之間的關係是這樣子滴:

pool鍊錶間通過d結構體中的next相鏈結(紅線部分),而pool->current則指向目前可參與分配記憶體的起始pool(藍線),貌似只有第乙個pool的curernt有指向相應的pool,其他的pool好像在create時並未賦值,具體怎樣還要再讀**,這個疑問留待以後解決吧。

新建立pool並從pool中分配size空間的**如下:

static void *

ngx_palloc_block(ngx_pool_t *pool, size_t size)

new = (ngx_pool_t *) m;

new->d.end = m + psize;

new->d.next = null;

new->d.failed = 0;

m += sizeof(ngx_pool_data_t);

m = ngx_align_ptr(m, ngx_alignment);

new->d.last = m + size;

current = pool->current;

/*將pool鍊錶中從current所指向的pool開始到鍊錶中的最後乙個pool的failed值+1,代表該pool分配失敗的次數,如果該次數大於4,則current指向其下乙個pool節點。

*/ for (p = current; p->d.next; p = p->d.next)

}//將新pool節點插入鍊錶末尾

p->d.next = new;

pool->current = current ? current : new;

return m;

}

分配大塊記憶體的**如下所示:

static void *

ngx_palloc_large(ngx_pool_t *pool, size_t size)

n = 0;

//試圖將p掛在原來已分配的large但large的alloc所指向的資料空間已被釋放的地方。

for (large = pool->large; large; large = large->next)

//只檢查large鍊錶的前三個節點,若前三個節點不可掛p,則跳出迴圈

if (n++ > 3)

}//從pool中分配large指標大小的空間(8位元組)

large = ngx_palloc(pool, sizeof(ngx_pool_large_t));

if (large == null)

large->alloc = p;

//將新分配的large節點放在鍊錶的表頭,next指向原來的表頭節點,即從頭插入新節點。

large->next = pool->large;

pool->large = large;

return p;

}

第一次申請large空間的結果如下圖所示:

第二次申請large空間的結果為:

為何要把large節點插入為表頭的位置呢,個人推理該方法避免了沒插入乙個新節點必須遍歷真個large鍊錶的不必要開銷。

以下為加入將新的cleanup節點加入cleanup鍊錶的**:

ngx_pool_cleanup_t *

ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)

//從pool池中分配size大小的資料空間

if (size)

} else

c->handler = null;

//將新節點插入表頭中

c->next = p->cleanup;

p->cleanup = c;

ngx_log_debug1(ngx_log_debug_alloc, p->log, 0, "add cleanup: %p", c);

return c;

}

第一次加入cleanup的結果如下圖所示:

nginx記憶體管理方面的核心**已經解析完畢了,若有分析錯誤的地方望指正。

nginx 記憶體池

nginx對記憶體的管理由其內部的記憶體池實現,nginx在 src os unix ngx alloc.h c中定義了基本的記憶體分配操作,如malloc等。記憶體池部分的操作在 src core ngx palloc.h c 中實現。乙個基本的nginx記憶體池結構如下所示 由上圖可知,ngin...

C 記憶體管理 記憶體池

很多內容來自於網際網路,如有侵權,請告知。另外,從 收穫很多,在此表示感謝。我們寫程式經常需要 malloc 和 new 一塊記憶體出來,這些記憶體是在堆上進行分配的,在堆上分配的記憶體和在棧上分配的記憶體不同,可以長久的儲存。堆是什麼 可以把你的程序空間 想象成 4g 大小的記憶體 32 為機子上...

C 記憶體管理 記憶體池

引子 一 單獨類記憶體池 classa intget void operator new size t void operator delete void size t private a next static a freestore 指向可用首位址 static const int achunk...