為了自身使用的方便,nginx封裝了很多有用的數據結構,比如ngx_str_t ,ngx_array_t, ngx_pool_t 等等,對于內存池,nginx設計的十分精煉,值得我們學習,本文介紹內存池基本知識,nginx內存池的初始化配置技術講解
ngx_cycle 的初始化
整個初始化過程中,最重要的就是全局變量 nginx_cycle 的初始化,很多變量都是在這個過程中初始化的
nginx_cycle 又是通過兩個局部變量 init_cycle 和 cycle 實現初始化的
事實上,日志初始化也可以算是對 nginx_cyle 的初始化,因為在代碼中接下來馬上要發生的就是一個賦值
ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
init_cycle.log = log;
ngx_cycle = &init_cycle;
// 創建內存池 1kb
init_cycle.pool = ngx_create_pool(1024, log);
if (init_cycle.pool == null) {
return 1;
}
// 保存調用參數到全局變量,init_cycle 只用于提供 log 參數
if (ngx_save_argv(&init_cycle, argc, argv) != ngx_ok) {
return 1;
}
// 保存配置文件路徑、程序運行路徑、調用參數到 init_cycle
if (ngx_process_options(&init_cycle) != ngx_ok) {
return 1;
}
// 獲取操作系統信息、cpu信息、最大連接數、是否支持非阻塞連接等
if (ngx_os_init(log) != ngx_ok) {
return 1;
}
/*
* ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
*/
// 對齊校驗表
if (ngx_crc32_table_init() != ngx_ok) {
return 1;
}
// 獲取所有繼承連接fd的相關信息
if (ngx_add_inherited_sockets(&init_cycle) != ngx_ok) {
return 1;
}
內存池
nginx 是通過資源集中管理的方式管理資源的,即打開所有即將要用的資源,以備隨時取用,無論是文件還是內存
這樣做的好處是避免了每次創建、打開資源造成的性能消耗
因此,便有了內存池模塊,用來集中申請內存資源并進行內存資源的管理和分配
內存池結構:
// struct ngx_pool_data_t
// 內存池數據塊結構 {{{
typedef struct {
u_char *last; // 當前內存分配的結束位置
u_char *end; // 內存池的結束位置
ngx_pool_t *next; // 下一內存池
ngx_uint_t failed; // 內存分配失敗計數
} ngx_pool_data_t; // }}}
// struct ngx_pool_s
// 內存池結構 {{{
struct ngx_pool_s {
ngx_pool_data_t d; // 內存池數據塊
size_t max; // 待分配內存大小
ngx_pool_t *current; // 指向當前內存池起始位置
ngx_chain_t *chain;
ngx_pool_large_t *large; // 指向大塊內存分配
ngx_pool_cleanup_t *cleanup; // 析構函數
ngx_log_t *log; // 內存分配相關的log
}; // }}}
在這個函數中,使用了一個封裝好的函數 ngx_memalign,這個函數是對系統中按照數據對齊方式分配內存的函數的封裝,在不同的系統中實現方式不同,通過宏定義,實現了操作系統的適配,這是一個很漂亮的技巧
#if (ngx_have_posix_memalign)
// void * ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
// 用數據對齊的方式進行內存分配 {{{
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
void *p;
int err;
// size 單位是 byte 而不是 bit
err = posix_memalign(&p, alignment, size);
if (err) {
ngx_log_error(ngx_log_emerg, log, err,
posix_memalign(%uz, %uz) failed, alignment, size);
p = null;
}
ngx_log_debug3(ngx_log_debug_alloc, log, 0,
posix_memalign: %p:%uz @%uz, p, size, alignment);
return p;
} // }}}
#elif (ngx_have_memalign)
// void * ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
// 用數據對齊的方式進行內存分配 {{{
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
所有有關內存分配的系統調用函數的封裝都定義在 ngx_alloc.c 文件中
這里用到了 posix_memalign 系統調用,使用這個系統調用分配出來的內存是默認按照第二個參數的大小對齊的,這樣在進行數據讀寫的時候,cpu可以周期地對整塊數據進行讀寫,很大程度的節省了cpu時間
這個系統調用所分配的內存也是存在于堆內存中的,可以使用 free 函數進行釋放,不過 malloc 分配的內存默認也是對齊的,它相對于 malloc 的優勢僅僅在于可以指定默認對齊大小。
函數完成了內存池的初步分配,執行后 pool 取值:
$23 = (ngx_pool_t *) 0x80fe9f0
(gdb) p *init_cycle.pool
$24 = {
d = {
last = 0x80fea18,
end = 0x80fedf0,
next = 0x0,
failed = 0
},
max = 984,
current = 0x80fe9f0,
chain = 0x0,
large = 0x0,
cleanup = 0x0,
log = 0x80e3020 <ngx_log>
}
如下圖所示:
服務器托管服務總得有些優惠吧?華南云服務器便宜chrome瀏覽器怎么自動運行flash chrome自動運行flash的設置方法阿里云香港VPS租用價格低至119元一年域名解析后打不開-其他問題電腦ip地址在哪看_電腦查看IP地址的方法網站怎么換新域名?網站更換新域名有什么方法?請幫忙查看這個站點配置是否有不正確的