日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Nginx >内容正文

Nginx

Nginx源码分析-内存池

發(fā)布時間:2025/3/15 Nginx 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Nginx源码分析-内存池 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文轉(zhuǎn)自淘寶平臺http://www.tbdata.org/archives/1390,不是為了奪他人之美,只是覺得寫得很好,怕淘寶萬一刪掉就找不到了,放在這里保存一下。大家可以直接鏈接過去,他們那個頁面做的還是不錯的。


Nginx源碼分析-內(nèi)存池

Nginx的內(nèi)存池實現(xiàn)得很精巧,代碼也很簡潔。總的來說,所有的內(nèi)存池基本都一個宗旨:申請大塊內(nèi)存,避免“細水長流”。

一、創(chuàng)建一個內(nèi)存池

nginx內(nèi)存池主要有下面兩個結(jié)構(gòu)來維護,他們分別維護了內(nèi)存池的頭部和數(shù)據(jù)部。此處數(shù)據(jù)部就是供用戶分配小塊內(nèi)存的地方。

//該結(jié)構(gòu)用來維護內(nèi)存池的數(shù)據(jù)塊,供用戶分配之用。 typedef struct {u_char *last; //當前內(nèi)存分配結(jié)束位置,即下一段可分配內(nèi)存的起始位置u_char *end; //內(nèi)存池結(jié)束位置ngx_pool_t *next; //鏈接到下一個內(nèi)存池ngx_uint_t failed; //統(tǒng)計該內(nèi)存池不能滿足分配請求的次數(shù) } ngx_pool_data_t; //該結(jié)構(gòu)維護整個內(nèi)存池的頭部信息。 struct ngx_pool_s {ngx_pool_data_t d; //數(shù)據(jù)塊size_t max; //數(shù)據(jù)塊的大小,即小塊內(nèi)存的最大值ngx_pool_t *current; //保存當前內(nèi)存池ngx_chain_t *chain; //可以掛一個chain結(jié)構(gòu)ngx_pool_large_t *large; //分配大塊內(nèi)存用,即超過max的內(nèi)存請求ngx_pool_cleanup_t *cleanup; //掛載一些內(nèi)存池釋放的時候,同時釋放的資源。ngx_log_t *log; };


有了上面的兩個結(jié)構(gòu),就可以創(chuàng)建一個內(nèi)存池了,nginx用來創(chuàng)建一個內(nèi)存池的接口是:ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)(位于src/core/ngx_palloc.c中);調(diào)用這個函數(shù)就可以創(chuàng)建一個大小為size的內(nèi)存池了。這里,我用內(nèi)存池的結(jié)構(gòu)圖來展示,就不做具體的代碼分析了。

ngx_create_pool接口函數(shù)就是分配上圖這樣的一大塊內(nèi)存,然后初始化好各個頭部字段(上圖中的彩色部分)。紅色表示的四個字段就是來自于上述的第一個結(jié)構(gòu),維護數(shù)據(jù)部分,由圖可知:last是用戶從內(nèi)存池分配新內(nèi)存的開始位置,end是這塊內(nèi)存池的結(jié)束位置,所有分配的內(nèi)存都不能超過end。藍色表示的max字段的值等于整個數(shù)據(jù)部分的長度,用戶請求的內(nèi)存大于max時,就認為用戶請求的是一個大內(nèi)存,此時需要在紫色表示的large字段下面單獨分配;用戶請求的內(nèi)存不大于max的話,就是小內(nèi)存申請,直接在數(shù)據(jù)部分分配,此時將會移動last指針。

二、分配小塊內(nèi)存(size <= max)

上面創(chuàng)建好了一個可用的內(nèi)存池了,也提到了小塊內(nèi)存的分配問題。nginx提供給用戶使用的內(nèi)存分配接口有:
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和ngx_pnalloc都是從內(nèi)存池里分配size大小內(nèi)存,至于分得的是小塊內(nèi)存還是大塊內(nèi)存,將取決于size的大小;他們的不同之處在于,palloc取得的內(nèi)存是對齊的,pnalloc則否。ngx_pcalloc是直接調(diào)用palloc分配好內(nèi)存,然后進行一次0初始化操作。ngx_pmemalign將在分配size大小的內(nèi)存并按alignment對齊,然后掛到large字段下,當做大塊內(nèi)存處理。下面用圖形展示一下分配小塊內(nèi)存的模型:

上圖這個內(nèi)存池模型是由上3個小內(nèi)存池構(gòu)成的,由于第一個內(nèi)存池上剩余的內(nèi)存不夠分配了,于是就創(chuàng)建了第二個新的內(nèi)存池,第三個內(nèi)存池是由于前面兩個內(nèi)存池的剩余部分都不夠分配,所以創(chuàng)建了第三個內(nèi)存池來滿足用戶的需求。由圖可見:所有的小內(nèi)存池是由一個單向鏈表維護在一起的。這里還有兩個字段需要關(guān)注,failed和current字段。failed表示的是當前這個內(nèi)存池的剩余可用內(nèi)存不能滿足用戶分配請求的次數(shù),即是說:一個分配請求到來后,在這個內(nèi)存池上分配不到想要的內(nèi)存,那么就failed就會增加1;這個分配請求將會遞交給下一個內(nèi)存池去處理,如果下一個內(nèi)存池也不能滿足,那么它的failed也會加1,然后將請求繼續(xù)往下傳遞,直到滿足請求為止(如果沒有現(xiàn)成的內(nèi)存池來滿足,會再創(chuàng)建一個新的內(nèi)存池)。current字段會隨著failed的增加而發(fā)生改變,如果current指向的內(nèi)存池的failed達到了4的話,current就指向下一個內(nèi)存池了。猜測:4這個值應該是作者的經(jīng)驗值,或者是一個統(tǒng)計值。

三、大塊內(nèi)存的分配(size > max)

大塊內(nèi)存的分配請求不會直接在內(nèi)存池上分配內(nèi)存來滿足,而是直接向操作系統(tǒng)申請這么一塊內(nèi)存(就像直接使用malloc分配內(nèi)存一樣),然后將這塊內(nèi)存掛到內(nèi)存池頭部的large字段下。內(nèi)存池的作用在于解決小塊內(nèi)存池的頻繁申請問題,對于這種大塊內(nèi)存,是可以忍受直接申請的。同樣,用圖形展示大塊內(nèi)存申請模型:

注意每塊大內(nèi)存都對應有一個頭部結(jié)構(gòu)(next&alloc),這個頭部結(jié)構(gòu)是用來將所有大內(nèi)存串成一個鏈表用的。這個頭部結(jié)構(gòu)不是直接向操作系統(tǒng)申請的,而是當做小塊內(nèi)存(頭部結(jié)構(gòu)沒幾個字節(jié))直接在內(nèi)存池里申請的。這樣的大塊內(nèi)存在使用完后,可能需要第一時間釋放,節(jié)省內(nèi)存空間,因此nginx提供了接口函數(shù):ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);此函數(shù)專門用來釋放某個內(nèi)存池上的某個大塊內(nèi)存,p就是大內(nèi)存的地址。ngx_pfree只會釋放大內(nèi)存,不會釋放其對應的頭部結(jié)構(gòu),畢竟頭部結(jié)構(gòu)是當做小內(nèi)存在內(nèi)存池里申請的;遺留下來的頭部結(jié)構(gòu)會作下一次申請大內(nèi)存之用。

四、cleanup資源


可以看到所有掛載在內(nèi)存池上的資源將形成一個循環(huán)鏈表,一路走來,發(fā)現(xiàn)鏈表這種看似簡單的數(shù)據(jù)結(jié)構(gòu)卻被頻繁使用。由圖可知,每個需要清理的資源都對應有一個頭部結(jié)構(gòu),這個結(jié)構(gòu)中有一個關(guān)鍵的字段handler,handler是一個函數(shù)指針,在掛載一個資源到內(nèi)存池上的時候,同時也會注冊一個清理資源的函數(shù)到這個handler上。即是說,內(nèi)存池在清理cleanup的時候,就是調(diào)用這個handler來清理對應的資源。比如:我們可以將一個開打的文件描述符作為資源掛載到內(nèi)存池上,同時提供一個關(guān)閉文件描述的函數(shù)注冊到handler上,那么內(nèi)存池在釋放的時候,就會調(diào)用我們提供的關(guān)閉文件函數(shù)來處理文件描述符資源了。

五、內(nèi)存的釋放

nginx只提供給了用戶申請內(nèi)存的接口,卻沒有釋放內(nèi)存的接口,那么nginx是如何完成內(nèi)存釋放的呢?總不能一直申請,用不釋放啊。針對這個問題,nginx利用了web server應用的特殊場景來完成;一個web server總是不停的接受connection和request,所以nginx就將內(nèi)存池分了不同的等級,有進程級的內(nèi)存池、connection級的內(nèi)存池、request級的內(nèi)存池。也就是說,創(chuàng)建好一個worker進程的時候,同時為這個worker進程創(chuàng)建一個內(nèi)存池,待有新的連接到來后,就在worker進程的內(nèi)存池上為該連接創(chuàng)建起一個內(nèi)存池;連接上到來一個request后,又在連接的內(nèi)存池上為request創(chuàng)建起一個內(nèi)存池。這樣,在request被處理完后,就會釋放request的整個內(nèi)存池,連接斷開后,就會釋放連接的內(nèi)存池。因而,就保證了內(nèi)存有分配也有釋放。

總結(jié):通過內(nèi)存的分配和釋放可以看出,nginx只是將小塊內(nèi)存的申請聚集到一起申請,然后一起釋放。避免了頻繁申請小內(nèi)存,降低內(nèi)存碎片的產(chǎn)生等問題

總結(jié)

以上是生活随笔為你收集整理的Nginx源码分析-内存池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲久草 | 老司机精品视频在线播放 | 丁香六月欧美 | 日美一级片 | 影音先锋天堂网 | 美女啪啪无遮挡 | 在线观看羞羞漫画 | 粗大的内捧猛烈进出在线视频 | 久久精品视频在线播放 | 精品国产精品三级精品av网址 | 成年人网站免费视频 | 超碰综合网| 国产精品69久久久 | 亚洲中文在线一区 | 美女自拍偷拍 | 免费视频www在线观看网站 | 久久东京 | 国产精品毛片久久久久久 | 在线免费观看污片 | 亚洲私人影院 | 一级片免费视频 | 亚洲综合干 | 日韩欧美视频免费在线观看 | 天堂va欧美va亚洲va老司机 | 亚洲天堂一级 | 日韩欧美国产综合 | 香蕉久久精品 | 超碰在线国产 | 日本xxxxxxxxx| 日本在线第一页 | 国产亚洲一区二区三区 | 奇米第四色首页 | 成年人网站免费在线观看 | 中文字幕一二三四区 | 无码熟妇αⅴ人妻又粗又大 | 黑人巨大猛交丰满少妇 | 97在线免费公开视频 | 欧美日韩一区二区在线观看视频 | 国产亚洲精品久久久久四川人 | 毛片1000部免费看 | 三度诱惑免费版电影在线观看 | 日本一区二区三区在线看 | 国产天堂在线观看 | 8x8ⅹ国产精品一区二区 | 日韩精品中文在线 | 国产乱淫av公 | 91日韩在线 | 国产精品久久免费视频 | 欧美性xxxxx极品少妇 | 午夜精品视频在线观看 | 国产精品久久久久免费 | 男女啊啊啊视频 | 久久福利影院 | 国产精品一区二区在线观看 | 久久久久久久久久久久97 | 激情五月在线观看 | 亚洲精品乱码久久久久久按摩观 | 日韩诱惑 | 熟妇女人妻丰满少妇中文字幕 | 欧美一区二区三区视频在线 | 国产www在线观看 | 无码人妻精品丰满熟人区 | 亚洲国产片 | 中文字幕在线观看免费 | 奇米影视首页 | 国产资源在线免费观看 | 人人妻人人澡人人爽人人dvd | 精品成人一区二区 | 骚视频在线观看 | 爱上av | 久久久久久久久久一区二区 | 暖暖av在线 | 成人短视频在线播放 | 中文国产在线观看 | 日韩视频国产 | 色999在线观看 | 日韩乱码人妻无码中文字幕久久 | 麻豆久久久久久 | 黄色图片小说 | www在线免费观看 | 国产盗摄视频在线观看 | 国产自产精品 | 日本高清三区 | jizz免费 | 岛国精品一区二区 | 欧美黑粗硬 | 男人深夜网站 | 欧美性色网站 | 亚洲精品短视频 | 日韩精品视频三区 | 国产成人精品无码片区在线 | 美女裸片| 日韩a视频 | 国产一区二三区 | 老司机深夜福利网站 | 波多野结衣在线影院 | 91导航 | 色婷婷电影网 | 久久成|