nginx 記憶體池

2021-07-09 05:37:07 字數 2995 閱讀 6360

nginx對記憶體的管理由其內部的記憶體池實現,nginx在/src/os/unix/ngx_alloc.h/.c中定義了基本的記憶體分配操作,如malloc等。記憶體池部分的操作在/src/core/ngx_palloc.(h/c)中實現。

乙個基本的nginx記憶體池結構如下所示

由上圖可知,nginx通過將多個記憶體塊串聯成煉表以形成乙個記憶體池的,其中每個記憶體塊都包含了乙個固定頭部(如每個記憶體塊頭部的藍色部分d),固定頭部記錄了每個記憶體塊的記憶體使用相關資訊,同時每個記憶體池還包含了乙個頭部(如鍊錶首個元素的紅色部分),其中儲存了記憶體池的相關資訊。

typedef struct  ngx_pool_data_t;
sizeof(ngx_pool_data_t)=16位元組,即記憶體池中除了頭節點外的其他每個節點的起始16位元組都是用來儲存該記憶體塊的使用資訊的。

struct ngx_pool_s ;
sizeof(struct ngx_pool_s )=40,即記憶體池頭節點的前40個位元組是用於儲存整個記憶體池和當前節點的相關資訊的。

記憶體池主要提供了以下操作:

下面將依次進行介紹。

ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *

log)

eg:當執行完ngx_create_pool(1024,log)後,得到的結果如下:

則當前記憶體池只有乙個節點,在該節點的前40位元組中記錄了當前記憶體池的相關資訊,而從p->d.last到p->d.end之間的984位元組可用於記憶體分配,因此p->max=984

void

*ngx_palloc(ngx_pool_t *pool, size_t size)

p = p->d.next; //1、 2當前記憶體塊中剩餘空間不足以滿足要求,則依次變了記憶體池的下乙個節點,以找到有足夠剩餘空間的記憶體塊,並分配記憶體

} while (p);

return ngx_palloc_block(pool, size); //1、3記憶體池中所有節點都不滿足要求,則重新分配乙個記憶體塊

}return ngx_palloc_large(pool, size); //2、大塊分配,分配乙個大塊記憶體,並加入到large鍊錶中

}

由上可知,在nginx記憶體池中申請記憶體主要分為兩種情況:

待分配的記憶體size< p->max,即可以在記憶體池中一次分配成功,為小塊分配

所需記憶體size>p->max,即超過了記憶體池每次可分配的最大空間,為大塊分配

對於小塊分配,可能有以下幾種情況:

1、在記憶體池當前可用節點中可以分配成功

2、在記憶體池的其他可用節點中可以分配成功

3、當前記憶體池中的所有節點都不滿足要求,此時則需要重新建立乙個記憶體塊,由於size<= p->max,因此此時可以分配成功

對於以上三種情況,分別如下圖所示。

1、 當所需記憶體size=300位元組時,在記憶體池鍊錶的當前節點中就可以分配成功,直接在當前節點中分配

2、當所需記憶體size=600位元組時,記憶體池的當前節點不足以分配所需大小的記憶體,因此遍歷鍊錶,找到下乙個滿足要求的節點,在該節點中分配記憶體,如圖所示,此時在第二個節點中可以滿足要求

3、當所需記憶體size=800位元組時,記憶體池所有節點都不足以分配該大小的記憶體,因此需要重新建立乙個節點,對於乙個新節點,其可用空間為1024-16=1008位元組》(p->max),因此一定可以滿足要求

對於大塊分配,如size=1000>(p->max)時,則需要呼叫 ngx_palloc_large(pool, size); 分配乙個大塊記憶體,並將其插入到記憶體池大塊記憶體鍊錶large鍊錶的頭部。

另一種記憶體分配ngx_pnalloc()與此操作基本相同,只是不再要求返回的記憶體位址是位元組對齊的。

重置記憶體池的操作主要是釋放large鍊錶中的所有大塊記憶體,重置所有小塊記憶體的起始位址和失敗次數,並將記憶體池的current指向記憶體池的頭節點

void

ngx_reset_pool(ngx_pool_t *pool)

}for (p = pool; p; p = p->d.next)

pool->current = pool; //將記憶體池的current指標指向記憶體池的頭節點

pool->chain =

null;

pool->large =

null;

}

在nginx中,使用者只能主動釋放大塊記憶體,小塊記憶體需要等待記憶體池銷毀時才能一起釋放

ngx_int_t

ngx_pfree(ngx_pool_t *pool, void

*p) //只能釋放large鍊錶中的記憶體塊,記憶體池中的其他節點只能等到記憶體池銷毀時統一釋放

}return ngx_declined;

}

nginx銷毀記憶體池所執行的主要操作包括:依次執行每個清理函式,釋放所有的大塊記憶體,釋放所有的小塊記憶體

void

ngx_destroy_pool(ngx_pool_t *pool)

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

}for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) }}

nginx記憶體池管理

在src core ngx palloc.h中定義了記憶體池相關的結構體 記憶體相關的 記憶體池 結構體 struct ngx pool cleanup s 大塊資料分配結構體 struct ngx pool large s 記憶體池中資料結構體 typedef struct ngx pool da...

Nginx基礎知識 Nginx記憶體池分析

1.記憶體池結構定義 struct ngx pool s typedef struct ngx pool data t 這兩個結構體涵蓋了nginx記憶體池的大部分內容.在我64位機器上 sizeof ngx pool data t 32 sizeof struct ngx pool s 80 我這...

記憶體池 C 記憶體池

c c 下記憶體管理是讓幾乎每乙個程式設計師頭疼的問題,分配足夠的記憶體 追蹤記憶體的分配 在不需要的時候釋放記憶體 這個任務相當複雜。1.呼叫malloc new,系統需要根據 最先匹配 最優匹配 或其他演算法在記憶體空閒塊表中查詢一塊空閒記憶體,呼叫free delete,系統可能需要合併空閒記...