Nginx學(xué)習(xí)筆記(三):封裝的數(shù)據(jù)結(jié)構(gòu)

前言

不能保證每天都有時(shí)間學(xué)這個(gè),畢竟其他方面還有很多的事情需要做感挥,但一定會(huì)利用好時(shí)間缩搅,充實(shí)自己。另外链快,大概掃了下Nginx自己封裝的數(shù)據(jù)結(jié)構(gòu)類型誉己,確實(shí)還是蠻多的。所以域蜗,暫時(shí)打算學(xué)一點(diǎn)巨双,更新一點(diǎn)。這一篇也主要是為自己開發(fā)一個(gè)簡單HTTP模塊做準(zhǔn)備霉祸。

封裝的數(shù)據(jù)結(jié)構(gòu)

Nginx為了做到跨平臺(tái)筑累,追求極致高效,自身定義丝蹭、封裝了一些數(shù)據(jù)結(jié)構(gòu)慢宗。就我個(gè)人來說,無論是對(duì)這一類統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)的封裝風(fēng)格奔穿,還是其中的封裝技巧(盡可能地少占用內(nèi)存)镜沽,都是非常喜歡,大贊一個(gè)贱田。

1)整型 <ngx_config.h>

typedef intptr_t? ? ? ? ngx_int_t;

typedef uintptr_t? ? ? ngx_uint_t;

C99 標(biāo)準(zhǔn)定義了 intptr_t 和 uintptr_t 類型是給一個(gè)可以持有一個(gè)指針值的整型變量缅茉。

2)字符串型 <ngx_string.h>

typedef struct {

? ? size_t? ? ? len;? // 指向字符串首字符地址

? ? u_char? ? *data; // 字符串長度

} ngx_str_t;

可以看出,這里基本沒有'\0'什么事了男摧。這種封裝的優(yōu)點(diǎn):1蔬墩,減少計(jì)算字符串長度次數(shù),可以直接用耗拓;2拇颅,可以重復(fù)引用一段字符串內(nèi)存,長度表示結(jié)束乔询。這樣樟插,不用對(duì)一段字符串再copy一份自己的副本,因?yàn)閐ata指針可以指向任何字符串地址竿刁,這樣可以減少不必要的內(nèi)存分配與拷貝岸夯。也因?yàn)檫@個(gè)特性,Nginx中必須謹(jǐn)慎對(duì)一段字符串做出修改们妥;另外猜扮,任何試圖將ngx_str_t的data成員當(dāng)作字符串來使用,都可能導(dǎo)致內(nèi)存越界监婶!

因?yàn)椴淮嬖凇甛0’旅赢,Nginx專門提供自己有關(guān)ngx_str_t的操作的API齿桃。簡單筆記:

// 以{...}括住,只適用于字符串賦值初始化煮盼,計(jì)算str長度為sizeof關(guān)鍵字短纵,因此str為字符串常量!? ? ?

#define ngx_string(str)? ? { sizeof(str) - 1, (u_char *) str }

#define ngx_null_string? ? { 0, NULL }

// 字符串賦值僵控,text為字符串常量香到!因?yàn)槭莾尚写a,在if/for/while等語句中單獨(dú)使用需要用花括號(hào)括起來报破!

#define ngx_str_set(str, text)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \

? ? (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text

#define ngx_str_null(str)? (str)->len = 0; (str)->data = NULL?

另外Nginx簡單封裝了glibc的字符串操作API悠就,具體見ngx_string.h。 ??

3)鏈表容器 <ngx_list.h>

/* 描述鏈表的一個(gè)結(jié)點(diǎn)充易,此節(jié)點(diǎn)實(shí)際上是一個(gè)數(shù)組梗脾,擁有一段連續(xù)內(nèi)存 */

typedef struct ngx_list_part_s? ngx_list_part_t;

struct ngx_list_part_s {

? ? void? ? ? ? ? ? *elts;? // 指向數(shù)組起始地址

? ? ngx_uint_t? ? ? ? nelts;? // 表示數(shù)組中已經(jīng)使用多少個(gè)元素,其值 <= ngx_list_t中的nalloc

? ? ngx_list_part_t? *next;? // 下一個(gè)鏈表節(jié)點(diǎn)

};

/* 描述整個(gè)鏈表 */

typedef struct {

? ? ngx_list_part_t? *last;? // 鏈表尾節(jié)點(diǎn)

? ? ngx_list_part_t? part;? // 鏈表首節(jié)點(diǎn)

? ? size_t? ? ? ? ? ? size;? // 鏈表的每一個(gè)節(jié)點(diǎn)實(shí)質(zhì)上是一個(gè)數(shù)組盹靴,但數(shù)組元素的類型是不確定的炸茧,由size表示每一個(gè)數(shù)組元素能夠存儲(chǔ)的最大值

? ? ngx_uint_t? ? ? ? nalloc; // 表示每一個(gè)ngx_list_part_t節(jié)點(diǎn)的容量

? ? ngx_pool_t? ? ? *pool;? // 鏈表中管理內(nèi)存分配的內(nèi)存池對(duì)象

} ngx_list_t;?

給出書中簡圖,一種可能的ngx_list_t鏈表的內(nèi)存分布結(jié)構(gòu)稿静。

對(duì)于鏈表梭冠,Nginx也提供了一組接口:

ngx_list_create接口用于創(chuàng)建新的鏈表;

ngx_list_init接口初始化一個(gè)已有鏈表改备;

ngx_list_push接口用于添加新元素控漠。具體情況詳見<ngx_list.c>。

4)動(dòng)態(tài)數(shù)組容器 <ngx_array.h>

typedef struct {

? ? void? ? ? ? *elts;? // 指向數(shù)組起始地址

? ? ngx_uint_t? nelts;? // 表示數(shù)組中已經(jīng)使用多少個(gè)元素绍妨,其值 <= ngx_list_t中的nalloc

? ? size_t? ? ? size;? // 一個(gè)數(shù)組元素能夠存儲(chǔ)的最大值

? ? ngx_uint_t? nalloc; // 當(dāng)nelts增長到達(dá)nalloc 時(shí)析苫,如果再往此數(shù)組中存儲(chǔ)元素蜕猫,則會(huì)引發(fā)數(shù)組的擴(kuò)容肖方。

? ? ? ? ? ? // 數(shù)組的容量將會(huì)擴(kuò)展到原有容量的2倍大小掰茶。實(shí)際上是分配新的一塊內(nèi)存肃叶,

? ? ? ? ? ? // 新的一塊內(nèi)存的大小是原有內(nèi)存大小的2倍滨攻。原有的數(shù)據(jù)會(huì)被拷貝到新的一塊內(nèi)存中钧舌。

? ? ngx_pool_t? *pool;? // 管理內(nèi)存分配的內(nèi)存池對(duì)象

} ngx_array_t;

基本上跟鏈表容器的節(jié)點(diǎn)元素一致禁熏,接口也類似垦巴,具體詳情見<ngx_array.c>媳搪。

ngx_array_t容器具備以下三個(gè)優(yōu)點(diǎn):

訪問速度快;

允許元素個(gè)數(shù)具備不確定性骤宣;

負(fù)責(zé)元素占用內(nèi)存的分配秦爆,這些內(nèi)存將由內(nèi)存池統(tǒng)一管理;

畫上書中圖描述下此結(jié)構(gòu)體及使用方法:

5)緩沖區(qū) <ngx_buf.h>

緩沖區(qū)ngx_buf_t是Nginx處理大數(shù)據(jù)的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)憔披,它既應(yīng)用于內(nèi)存數(shù)據(jù)也應(yīng)用于磁盤數(shù)據(jù)等限。

typedef struct ngx_buf_s? ngx_buf_t;

typedef void *? ? ? ? ? ? ngx_buf_tag_t;

struct ngx_buf_s {

? ? /* 表示從此為止開始處理內(nèi)存數(shù)據(jù)爸吮,同一個(gè)ngx_buf_t可能被多次反復(fù)處理 */

? ? u_char? ? ? ? ? *pos;


? ? /* Nginx有效處理的內(nèi)存結(jié)束地址 */

? ? u_char? ? ? ? ? *last;


? ? /* 處理文件時(shí),含義與pos望门、last相同 */

? ? off_t? ? ? ? ? ? file_pos;

? ? off_t? ? ? ? ? ? file_last;

? ? /* 如果ngx_buf_t緩沖區(qū)用于內(nèi)存形娇,這個(gè)則指向buf起始地址與尾地址...那上面兩字段毛意思,混亂中... */

? ? u_char? ? ? ? ? *start;? ? ? ? /* start of buffer */

? ? u_char? ? ? ? ? *end;? ? ? ? ? /* end of buffer */


? ? /* 表示當(dāng)前緩沖區(qū)類型 */

? ? ngx_buf_tag_t? ? tag;


? ? /* 引用的文件 */

? ? ngx_file_t? ? ? *file;


? ? /* 當(dāng)前緩沖區(qū)的影子緩沖區(qū)(筆記:很少用到筹误,不建議使用) */

? ? ngx_buf_t? ? ? *shadow;

? ? /* the buf's content could be changed */

? ? /* 源碼中有英文注釋桐早,翻譯為中文...

? ? * 以下均為標(biāo)志位,且其值置1的意義

? ? */

? ? /* 臨時(shí)內(nèi)存標(biāo)志位厨剪,表示數(shù)據(jù)在內(nèi)存中哄酝,可修改 */

? ? unsigned? ? ? ? temporary:1;

? ? /*

? ? * the buf's content is in a memory cache or in a read only memory

? ? * and must not be changed

? ? */

? ? /* 表示數(shù)據(jù)在內(nèi)存中,且不能被修改 */

? ? unsigned? ? ? ? memory:1;

? ? /* the buf's content is mmap()ed and must not be changed */

? ? /* 表示內(nèi)存是用mmap系統(tǒng)調(diào)用映射過來丽惶,不可被修改 */

? ? unsigned? ? ? ? mmap:1;

/* 表示可回收 */

? ? unsigned? ? ? ? recycled:1;


? ? /* buf緩沖區(qū)處理的是文件炫七,不是內(nèi)存 */

? ? unsigned? ? ? ? in_file:1;


? ? /* 需要執(zhí)行flush操作 */

? ? unsigned? ? ? ? flush:1;


? ? /* 使用同步方式(可能阻塞Nginx進(jìn)程,謹(jǐn)慎使用) */

? ? unsigned? ? ? ? sync:1;


? ? /* ngx_buf_t可由ngx_chain_t串聯(lián)钾唬,此標(biāo)志位表示當(dāng)前是最后一塊待處理的緩沖區(qū) */

? ? unsigned? ? ? ? last_buf:1;


? ? /* 表示是ngx_chain_t中最后一塊緩沖區(qū) */

? ? unsigned? ? ? ? last_in_chain:1;

/* 配合影子緩沖區(qū)使用万哪,表示最后一個(gè)影子緩沖區(qū) */

? ? unsigned? ? ? ? last_shadow:1;


? ? /* 表示當(dāng)親緩沖區(qū)屬于臨時(shí)文件 */

? ? unsigned? ? ? ? temp_file:1;

? ? /* STUB */ int? num;

};

ngx_buf_t是一種基本的數(shù)據(jù)結(jié)構(gòu),本質(zhì)上提供的僅僅是一些指針成員和標(biāo)志位抡秆。如果我們自定義一個(gè)ngx_buf_t結(jié)構(gòu)奕巍,則應(yīng)該根據(jù)業(yè)務(wù)需求自行定義。

5)緩沖區(qū)鏈表 <ngx_buf.h>

typedef struct ngx_chain_s? ? ? ngx_chain_t;? ? <ngx_core.h>

struct ngx_chain_s {? ? ? ? ? ? ? ? ? ? ? ? ? ? <ngx_buf.h>

? ? ngx_buf_t? ? *buf;? // 指向當(dāng)前緩沖區(qū)

? ? ngx_chain_t? *next; // 指向下一個(gè)儒士,如果是最后一個(gè)ngx_chain_t的止,必須置NULL

};

這個(gè)是與ngx_buf_t配合使用的鏈表結(jié)構(gòu)。摘下博文《Nginx模塊開發(fā)入門》簡圖:

總結(jié)

暫時(shí)沒法總結(jié)着撩。诅福。還沒體會(huì)這些數(shù)據(jù)的好處。對(duì)那個(gè)str_list_t的設(shè)計(jì)拖叙,比較喜歡氓润。

主要參考

《深入理解Nginx》

《Nginx從入門到精通》

《Nginx模塊開發(fā)入門》

---------------------

作者:時(shí)間文盲

來源:CSDN

原文:https://blog.csdn.net/fzy0201/article/details/17512119

版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接薯鳍!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咖气,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挖滤,更是在濱河造成了極大的恐慌崩溪,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斩松,死亡現(xiàn)場離奇詭異伶唯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)惧盹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門抵怎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奋救,“玉大人,你說我怎么就攤上這事反惕〕⑺遥” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵姿染,是天一觀的道長背亥。 經(jīng)常有香客問我,道長悬赏,這世上最難降的妖魔是什么狡汉? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮闽颇,結(jié)果婚禮上盾戴,老公的妹妹穿的比我還像新娘。我一直安慰自己兵多,他們只是感情好尖啡,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剩膘,像睡著了一般衅斩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怠褐,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天畏梆,我揣著相機(jī)與錄音,去河邊找鬼奈懒。 笑死奠涌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的磷杏。 我是一名探鬼主播溜畅,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茴丰!你這毒婦竟也來了达皿?” 一聲冷哼從身側(cè)響起天吓,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤贿肩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后龄寞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汰规,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年物邑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了溜哮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滔金。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茂嗓,靈堂內(nèi)的尸體忽然破棺而出餐茵,到底是詐尸還是另有隱情,我是刑警寧澤述吸,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布忿族,位于F島的核電站,受9級(jí)特大地震影響蝌矛,放射性物質(zhì)發(fā)生泄漏道批。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一入撒、第九天 我趴在偏房一處隱蔽的房頂上張望隆豹。 院中可真熱鬧,春花似錦茅逮、人聲如沸璃赡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鉴吹。三九已至,卻和暖如春惩琉,著一層夾襖步出監(jiān)牢的瞬間豆励,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國打工瞒渠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留良蒸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓伍玖,卻偏偏與公主長得像嫩痰,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窍箍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • request 在nginx中我們指的是http請(qǐng)求串纺,一個(gè)http請(qǐng)求,包含請(qǐng)求行椰棘、請(qǐng)求頭纺棺、請(qǐng)求體、響應(yīng)行邪狞、響應(yīng)頭...
    三生紙書閱讀 576評(píng)論 0 0
  • 前言 Nginx是當(dāng)前最流行的HTTP Server之一祷蝌,根據(jù)W3Techs的統(tǒng)計(jì),目前世界排名(根據(jù)Alexa)...
    GarfieldEr007閱讀 5,322評(píng)論 4 22
  • HTTP模塊的調(diào)用 worker 進(jìn)程會(huì)在一個(gè)for 循環(huán)里面反復(fù)調(diào)用事件模塊檢測網(wǎng)絡(luò)事件帆卓。 基本數(shù)據(jù)結(jié)構(gòu) 對(duì)整形...
    Spike_3154閱讀 1,581評(píng)論 0 1
  • 1. Nginx 介紹 Nginx是俄羅斯人編寫的十分輕量級(jí)的HTTP服務(wù)器,它的發(fā)音為“engine X”巨朦, 是...
    SkTj閱讀 676評(píng)論 1 0
  • 本文系轉(zhuǎn)載》》》》》》》》》》》》》》》》 編者按:高可用架構(gòu)分享及傳播在架構(gòu)領(lǐng)域具有典型意義的文章米丘,本文由陳科在...
    demop閱讀 8,068評(píng)論 0 7