內存分配相關
系統功能封裝
內存相關的操作主要在 os/unix/ngx_alloc.{h,c} 和 core/ngx_palloc.{h,c} 下
其中 os/unix/ngx_alloc.{h,c} 封裝了最基本的內存分配函數,是對c原有的malloc/free/memalign 等原有的函數的封裝,對應的函數為:
- ngx_alloc 使用malloc分配內存空間
- ngx_calloc 使用malloc分配內存空間,并且將空間內容初始化為0
- ngx_memalign 返回基于一個指定的alignment大小的數值為對齊基數的空間
- ngx_free 對內存的釋放操作
ngx的內存池
為了方便系統模塊對內存的使用,方便內存的管理,nginx自己實現了進程池的機制來進行內存的分配和釋放, 首先nginx會在特定的生命周期幫你統一建立內存池,當需要進行內存分配的時候統一通過內存池中的內存進行分配,最后nginx會在適當的時候釋放內存池的資源,開發者只要在需要的時候對內存進行申請即可,不用過多考慮內存的釋放等問題,大大提高了開發的效率。
內存池的主要結構為:
//ngx_palloc.h 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 ; }; //ngx_core.h typedef struct ngx_pool_s ? ? ? ?ngx_pool_t ; typedef struct ngx_chain_s ? ? ? ngx_chain_t ;
下面是我簡單畫的一個圖來描述這個結構:
link :? http://www.flickr.com/photos/rainx/3765612584/sizes/o/
下面解釋一下主要的幾個操作:
// 創建內存池 ngx_pool_t * ngx_create_pool ( size_t size , ngx_log_t * log );
大致的過程是創建使用 ngx_alloc 分配一個size大小的空間, 然后將? ngx_pool_t* ?指向這個空間, 并且初始化里面的成員, 其中
p -> d . last = ( u_char *) p + sizeof ( ngx_pool_t ); // 初始指向 ngx_pool_t 結構體后面 p -> d . end = ( u_char *) p + size ; // 整個結構的結尾后面 p -> max = ( size < NGX_MAX_ALLOC_FROM_POOL ) ? size : NGX_MAX_ALLOC_FROM_POOL ; // 最大不超過 NGX_MAX_ALLOC_FROM_POOL,也就是getpagesize()-1 大小
其他大都設置為null或者0
// 銷毀內存池 void ngx_destroy_pool ( ngx_pool_t * pool );
遍歷鏈表,所有釋放內存,其中如果注冊了clenup(也是一個鏈表結構), 會一次調用clenup 的 handler 進行清理。
// 重置內存池 void ngx_reset_pool ( ngx_pool_t * pool );
釋放所有large段內存, 并且將d->last指針重新指向 ngx_pool_t 結構之后(和創建時一樣)
// 從內存池里分配內存 void * ngx_palloc ( ngx_pool_t * pool , size_t size ); void * ngx_pnalloc ( ngx_pool_t * pool , size_t size ); void * ngx_pcalloc ( ngx_pool_t * pool , size_t size ); void * ngx_pmemalign ( ngx_pool_t * pool , size_t size , size_t alignment );
ngx_palloc的過程一般為,首先判斷待分配的內存是否大于 pool->max的大小,如果大于則使用 ngx_palloc_large 在 large 鏈表里分配一段內存并返回, 如果小于測嘗試從鏈表的 pool->current 開始遍歷鏈表,嘗試找出一個可以分配的內存,當鏈表里的任何一個節點都無法分配內存的時候,就調用 ngx_palloc_block 生成鏈表里一個新的節點, 并在新的節點里分配內存并返回, 同時, 還會將pool->current 指針指向新的位置(從鏈表里面pool->d.failed小于等于4的節點里找出) ,其他幾個函數也基本上為 ngx_palloc 的變種,實現方式大同小異
// 釋放指定的內存 ngx_int_t ngx_pfree ( ngx_pool_t * pool , void * p );
這個操作只有在內存在large鏈表里注冊的內存在會被真正釋放,如果分配的是普通的內存,則會在destory_pool的時候統一釋放.
// 注冊cleanup回叫函數(結構體) ngx_pool_cleanup_t * ngx_pool_cleanup_add ( ngx_pool_t * p , size_t size );
這個過程和我們之前經常使用的有些區別, 他首先在傳入的內存池中分配這個結構的空間(包括data段), 然后將為結構體分配的空間返回, 通過操作返回的ngx_pool_cleanup_t結構來添加回叫的實現。 ( 這個過程在nginx里面出現的比較多,也就是 xxxx_add 操作通常不是實際的添加操作,而是分配空間并返回一個指針,后續我們還要通過操作指針指向的空間來實現所謂的add )
下面是內存操作的一些例子 demo/basic_types/mem_op.c
#include <stdio.h> #include "ngx_config.h" #include "ngx_conf_file.h" #include "nginx.h" #include "ngx_core.h" #include "ngx_string.h" #include "ngx_palloc.h" volatile ngx_cycle_t ? * ngx_cycle ; void ngx_log_error_core ( ngx_uint_t level , ngx_log_t * log , ngx_err_t err , ? ? ? ? ? ? const char * fmt , ...) { } typedef struct example_s { ? ? int a ; ? ? char * b ; } example_t ; int main () { ? ? ngx_pool_t * pool ; ? ? example_t * exp ; ? ? char * s ; ? ? pool = ngx_create_pool ( 5000 , NULL ); ? ? printf ( "available pool regular pool free size is %d now\n" , ( ngx_uint_t ) ( pool -> d . end - pool -> d . last )); ? ? exp = ngx_palloc ( pool , sizeof ( example_t )) ; ? ? s = ngx_palloc ( pool , sizeof ( "hello,world" )); ? ? printf ( "available pool regular pool free size is %d now\n" , ( ngx_uint_t ) ( pool -> d . end - pool -> d . last )); ? ? exp -> a = 1 ; ? ? exp -> b = s ; ? ? strcpy ( s , "hello,world" ); ? ? printf ( "pool max is %d\n" , pool -> max ); ? ? printf ( "exp->a is %d, exp->b is %s\n" , exp -> a , exp -> b ); ? ? ngx_destroy_pool ( pool ); ? ? return 0 ; }
編譯運行結果
gcc ? - c - O - pipe ? - O - W - Wall - Wpointer - arith - Wno - unused - parameter - Wunused - function - Wunused - variable - Wunused - value - Werror - g - I ../../../ objs / - I ../../ os / unix / mem_op . c - I ../../ core / - I ../../ event / - I ../../ os / - o mem_op . o ?gcc - o mem_op mem_op . o ../../../ objs / src / core / ngx_ { string , palloc }. o ../../../ objs / src / os / unix / ngx_alloc . o - lcrypt - lpcre - lcrypto - lz rainx@rainx - laptop :~/ land / nginx - 0.7 . 61 / src / demo / basic_types$ ./ mem_op available pool regular pool free size is 4960 now available pool regular pool free size is 4940 now pool max is 4960 exp -> a is 1 , exp -> b is hello , world
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
