這個ngx_buf_t就是這個ngx_chain_t鏈表的每個節點的實際數據。該結構實際上是一種抽象的數據結構,它代表某種具體的數據。這個數據可能是指向內存中的某個緩沖區,也可能指向一個文件的某一部分,也可能是一些純元數據(元數據的作用在于指示這個鏈表的讀取者對讀取的數據進行不同的處理)。
該數據結構位于src/core/ngx_buf.h|c文件中。我們來看一下它的定義。
[](http:// "點擊提交Issue,反饋你的意見...")
struct ngx_buf_s {
u_char *pos;
u_char *last;
off_t file_pos;
off_t file_last;
u_char *start; /* start of buffer */
u_char *end; /* end of buffer */
ngx_buf_tag_t tag;
ngx_file_t *file;
ngx_buf_t *shadow;
/* the buf's content could be changed */
unsigned temporary:1;
/*
* the buf's content is in a memory cache or in a read only memory
* and must not be changed
*/
unsigned memory:1;
/* the buf's content is mmap()ed and must not be changed */
unsigned mmap:1;
unsigned recycled:1;
unsigned in_file:1;
unsigned flush:1;
unsigned sync:1;
unsigned last_buf:1;
unsigned last_in_chain:1;
unsigned last_shadow:1;
unsigned temp_file:1;
/* STUB */ int num;
};
| pos: | 當buf所指向的數據在內存里的時候,pos指向的是這段數據開始的位置。 |
|-----|-----|
| last: | 當buf所指向的數據在內存里的時候,last指向的是這段數據結束的位置。 |
| file_pos: | 當buf所指向的數據是在文件里的時候,file_pos指向的是這段數據的開始位置在文件中的偏移量。 |
| file_last: | 當buf所指向的數據是在文件里的時候,file_last指向的是這段數據的結束位置在文件中的偏移量。 |
| start: | 當buf所指向的數據在內存里的時候,這一整塊內存包含的內容可能被包含在多個buf中(比如在某段數據中間插入了其他的數據,這一塊數據就需要被拆分開)。那么這些buf中的start和end都指向這一塊內存的開始地址和結束地址。而pos和last指向本buf所實際包含的數據的開始和結尾。 |
| end: | 解釋參見start。 |
| tag: | 實際上是一個void*類型的指針,使用者可以關聯任意的對象上去,只要對使用者有意義。 |
| file: | 當buf所包含的內容在文件中時,file字段指向對應的文件對象。 |
| shadow: | 當這個buf完整copy了另外一個buf的所有字段的時候,那么這兩個buf指向的實際上是同一塊內存,或者是同一個文件的同一部分,此時這兩個buf的shadow字段都是指向對方的。那么對于這樣的兩個buf,在釋放的時候,就需要使用者特別小心,具體是由哪里釋放,要提前考慮好,如果造成資源的多次釋放,可能會造成程序崩潰! |
| temporary: | 為1時表示該buf所包含的內容是在一個用戶創建的內存塊中,并且可以被在filter處理的過程中進行變更,而不會造成問題。 |
| memory: | 為1時表示該buf所包含的內容是在內存中,但是這些內容卻不能被進行處理的filter進行變更。 |
| mmap: | 為1時表示該buf所包含的內容是在內存中, 是通過mmap使用內存映射從文件中映射到內存中的,這些內容卻不能被進行處理的filter進行變更。 |
| recycled: | 可以回收的。也就是這個buf是可以被釋放的。這個字段通常是配合shadow字段一起使用的,對于使用ngx_create_temp_buf 函數創建的buf,并且是另外一個buf的shadow,那么可以使用這個字段來標示這個buf是可以被釋放的。 |
| in_file: | 為1時表示該buf所包含的內容是在文件中。 |
| flush: | 遇到有flush字段被設置為1的的buf的chain,則該chain的數據即便不是最后結束的數據(last_buf被設置,標志所有要輸出的內容都完了),也會進行輸出,不會受postpone_output配置的限制,但是會受到發送速率等其他條件的限制。 |
| sync: | |
| last_buf: | 數據被以多個chain傳遞給了過濾器,此字段為1表明這是最后一個buf。 |
| last_in_chain: | 在當前的chain里面,此buf是最后一個。特別要注意的是last_in_chain的buf不一定是last_buf,但是last_buf的buf一定是last_in_chain的。這是因為數據會被以多個chain傳遞給某個filter模塊。 |
| last_shadow: | 在創建一個buf的shadow的時候,通常將新創建的一個buf的last_shadow置為1。 |
| temp_file: | 由于受到內存使用的限制,有時候一些buf的內容需要被寫到磁盤上的臨時文件中去,那么這時,就設置此標志 。 |
對于此對象的創建,可以直接在某個ngx_pool_t上分配,然后根據需要,給對應的字段賦值。也可以使用定義好的2個宏:
#define ngx_alloc_buf(pool) ?ngx_palloc(pool, sizeof(ngx_buf_t))
#define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
這兩個宏使用類似函數,也是不說自明的。
對于創建temporary字段為1的buf(就是其內容可以被后續的filter模塊進行修改),可以直接使用函數ngx_create_temp_buf進行創建。
[](http:// "點擊提交Issue,反饋你的意見...")
ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);
該函數創建一個ngx_but_t類型的對象,并返回指向這個對象的指針,創建失敗返回NULL。
對于創建的這個對象,它的start和end指向新分配內存開始和結束的地方。pos和last都指向這塊新分配內存的開始處,這樣,后續的操作可以在這塊新分配的內存上存入數據。
| pool: | 分配該buf和buf使用的內存所使用的pool。 |
|-----|-----|
| size: | 該buf使用的內存的大小。 |
為了配合對ngx_buf_t的使用,nginx定義了以下的宏方便操作。
#define ngx_buf_in_memory(b) ? ? ? ?(b->temporary || b->memory || b->mmap)
返回這個buf里面的內容是否在內存里。
#define ngx_buf_in_memory_only(b) ? (ngx_buf_in_memory(b) && !b->in_file)
返回這個buf里面的內容是否僅僅在內存里,并且沒有在文件里。
#define ngx_buf_special(b) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
? ?((b->flush || b->last_buf || b->sync) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
? ? && !ngx_buf_in_memory(b) && !b->in_file)
返回該buf是否是一個特殊的buf,只含有特殊的標志和沒有包含真正的數據。
#define ngx_buf_sync_only(b) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
? ?(b->sync ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
? ? && !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
返回該buf是否是一個只包含sync標志而不包含真正數據的特殊buf。
#define ngx_buf_size(b) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
? ?(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): ? ? ? ? ? ? ? ? ? ? ?\
? ? ? ? ? ? ? ? ? ? ? ? ? ?(b->file_last - b->file_pos))
返回該buf所含數據的大小,不管這個數據是在文件里還是在內存里。
- 上篇:nginx模塊開發篇
- nginx平臺初探
- 初探nginx架構
- nginx基礎概念
- connection
- request
- keepalive
- pipe
- lingering_close
- 基本數據結構
- ngx_str_t
- ngx_pool_t
- ngx_array_t
- ngx_hash_t
- ngx_hash_wildcard_t
- ngx_hash_combined_t
- ngx_hash_keys_arrays_t
- ngx_chain_t
- ngx_buf_t
- ngx_list_t
- ngx_queue_t
- nginx的配置系統
- 指令參數
- 指令上下文
- nginx的模塊化體系結構
- 模塊的分類
- nginx的請求處理
- handler模塊
- handler模塊簡介
- 模塊的基本結構
- 模塊配置結構
- 模塊配置指令
- 模塊上下文結構
- 模塊的定義
- handler模塊的基本結構
- handler模塊的掛載
- handler的編寫步驟
- 示例: hello handler 模塊
- handler模塊的編譯和使用
- 更多handler模塊示例分析
- http access module
- http static module
- http log module
- 過濾模塊
- 過濾模塊簡介
- 過濾模塊的分析
- upstream模塊
- upstream模塊
- upstream模塊接口
- memcached模塊分析
- 本節回顧
- 負載均衡模塊
- 配置
- 指令
- 鉤子
- 初始化配置
- 初始化請求
- peer.get和peer.free回調函數
- 本節回顧
- 其他模塊
- core模塊
- event模塊
- 模塊開發高級篇
- 變量
- 下篇:nginx原理解析篇
- nginx架構詳解
- nginx的源碼目錄結構
- nginx的configure原理
- 模塊編譯順序
- nginx基礎設施
- 內存池
- nginx的啟動階段
- 概述
- 共有流程
- 配置解析
- nginx的請求處理階段
- 接收請求流程
- http請求格式簡介
- 請求頭讀取
- 解析請求行
- 解析請求頭
- 請求體讀取
- 讀取請求體
- 丟棄請求體
- 多階段處理請求
- 多階段執行鏈
- POST_READ階段
- SERVER_REWRITE階段
- FIND_CONFIG階段
- REWRITE階段
- POST_REWRITE階段
- PREACCESS階段
- ACCESS階段
- POST_ACCESS階段
- TRY_FILES階段
- CONTENT階段
- LOG階段
- Nginx filter
- header filter分析
- body filter分析
- ngx_http_copy_filter_module分析
- ngx_http_write_filter_module分析
- subrequest原理解析
- https請求處理解析
- 附錄A 編碼風格
- 附錄B 常用API
- 附錄C 模塊編譯,調試與測試