ngx_list_t顧名思義,看起來好像是一個list的數據結構。這樣的說法,算對也不算對。因為它符合list類型數據結構的一些特點,比如可以添加元素,實現自增長,不會像數組類型的數據結構,受到初始設定的數組容量的限制,并且它跟我們常見的list型數據結構也是一樣的,內部實現使用了一個鏈表。
那么它跟我們常見的鏈表實現的list有什么不同呢?不同點就在于它的節點,它的節點不像我們常見的list的節點,只能存放一個元素,ngx_list_t的節點實際上是一個固定大小的數組。
在初始化的時候,我們需要設定元素需要占用的空間大小,每個節點數組的容量大小。在添加元素到這個list里面的時候,會在最尾部的節點里的數組上添加元素,如果這個節點的數組存滿了,就再增加一個新的節點到這個list里面去。
好了,看到這里,大家應該基本上明白這個list結構了吧?還不明白也沒有關系,下面我們來具體看一下它的定義,這些定義和相關的操作函數定義在src/core/ngx_list.h|c文件中。
[](http:// "點擊提交Issue,反饋你的意見...")
typedef struct {
ngx_list_part_t *last;
ngx_list_part_t part;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *pool;
} ngx_list_t;
| last: | 指向該鏈表的最后一個節點。 |
|-----|-----|
| part: | 該鏈表的首個存放具體元素的節點。 |
| size: | 鏈表中存放的具體元素所需內存大小。 |
| nalloc: | 每個節點所含的固定大小的數組的容量。 |
| pool: | 該list使用的分配內存的pool。 |
好,我們在看一下每個節點的定義。
[](http:// "點擊提交Issue,反饋你的意見...")
typedef struct ngx_list_part_s ngx_list_part_t;
struct ngx_list_part_s {
void *elts;
ngx_uint_t nelts;
ngx_list_part_t *next;
};
| elts: | 節點中存放具體元素的內存的開始地址。 |
|-----|-----|
| nelts: | 節點中已有元素個數。這個值是不能大于鏈表頭節點ngx_list_t類型中的nalloc字段的。 |
| next: | 指向下一個節點。 |
我們來看一下提供的一個操作的函數。
[](http:// "點擊提交Issue,反饋你的意見...")
ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);
該函數創建一個ngx_list_t類型的對象,并對該list的第一個節點分配存放元素的內存空間。
| pool: | 分配內存使用的pool。 |
|-----|-----|
| n: | 每個節點固定長度的數組的長度。 |
| size: | 存放的具體元素的個數。 |
| 返回值: | 成功返回指向創建的ngx_list_t對象的指針,失敗返回NULL。 |
[](http:// "點擊提交Issue,反饋你的意見...")
void *ngx_list_push(ngx_list_t *list);
該函數在給定的list的尾部追加一個元素,并返回指向新元素存放空間的指針。如果追加失敗,則返回NULL。
[](http:// "點擊提交Issue,反饋你的意見...")
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size);
該函數是用于ngx_list_t類型的對象已經存在,但是其第一個節點存放元素的內存空間還未分配的情況下,可以調用此函數來給這個list的首節點來分配存放元素的內存空間。
那么什么時候會出現已經有了ngx_list_t類型的對象,而其首節點存放元素的內存尚未分配的情況呢?那就是這個ngx_list_t類型的變量并不是通過調用ngx_list_create函數創建的。例如:如果某個結構體的一個成員變量是ngx_list_t類型的,那么當這個結構體類型的對象被創建出來的時候,這個成員變量也被創建出來了,但是它的首節點的存放元素的內存并未被分配。
總之,如果這個ngx_list_t類型的變量,如果不是你通過調用函數ngx_list_create創建的,那么就必須調用此函數去初始化,否則,你往這個list里追加元素就可能引發不可預知的行為,亦或程序會崩潰!
- 上篇: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 模塊編譯,調試與測試