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,系統可能需要合併空閒記...