Nginx 基本數據結構

概述

        在學習 Nginx 之前首先了解其基本的數據結構是非常重要的,這是入門必須瞭解的一個步驟。本節只是簡單介紹了 Nginx 對基本數據的一種封裝,包括 基本整型數據類型、字符串數據類型、緩衝區類型以及 chain 數據類型。

基本數據類型

整型數據

/* 基本數據結構 */

/* Nginx 簡單數據類型 */
/* 在文件 src/core/ngx_config.h 定義了基本的數據映射 */

typedef intptr_t        ngx_int_t;
typedef uintptr_t       ngx_uint_t;
typedef intptr_t        ngx_flag_t;
/* 其中 intptr_t uintptr_t 定義在文件 /usr/include/stdint.h 文件中*/

/* Types for `void *' pointers.  */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int		intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned long int	uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int			intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned int		uintptr_t;

/* 因此,Nginx 的簡單數據類型的操作和整型或指針類型類似 */

字符串類型

/* Nginx 字符串數據類型 */
/* Nginx 字符串類型是對 C 語言字符串類型的簡單封裝,
 * 其定義在 core/ngx_string.h 或 core/ngx_string.c 中
 * 定義了 ngx_str_t, ngx_keyval_t, ngx_variable_value_t
 */

/* ngx_str_t 在 u_char 的基礎上增加了字符串長度的信息,即len變量 */
typedef struct {
    size_t      len;    /* 字符串的長度 */
    u_char     *data;   /* 指向字符串的第一個字符 */
} ngx_str_t;


typedef struct {
    ngx_str_t   key;
    ngx_str_t   value;
} ngx_keyval_t;


typedef struct {
    unsigned    len:28;

    unsigned    valid:1;
    unsigned    no_cacheable:1;
    unsigned    not_found:1;
    unsigned    escape:1;

    u_char     *data;
} ngx_variable_value_t;
/* Nginx 字符串的初始化使用 ngx_string 或 ngx_null_string ,這兩個宏定義如下 */

#define ngx_string(str) {sizeof(str)-1, (u_char *) str}
#define ngx_null_string {0, NULL}

/* 若已經定義了 Nginx 字符串變量之後再賦值,則必須使用 ngx_str_set, ngx_str_null 宏定義*/

#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

/* 例如:*/
/* 正確寫法*/
ngx_str_t str1 = ngx_string("hello nginx");
ngx_str_t str2 = ngx_null_string;

/* 錯誤寫法*/
ngx_str_t str1, str2;
str1 = ngx_string("hello nginx");   /* 編譯出錯 */
str2 = ngx_null_string;             /* 編譯出錯 */

/* 正確寫法*/
ngx_str_t str1, str2;
ngx_str_set(&str1, "hello nginx");
ngx_str_null(&str2);
/* 注意:ngx_string 和 ngx_str_set 字符串參數必須是常量字符串,不能是變量字符串 */

內存池類型

內存池類型即是 ngx_pool_t ,有關內存池的講解可參考前文《Nginx 內存池管理

/* 內存池結構 */
/* 文件 core/ngx_palloc.h */
typedef struct {/* 內存池數據結構模塊 */
    u_char               *last; /* 當前內存分配的結束位置,即下一段可分配內存的起始位置 */
    u_char               *end;  /* 內存池的結束位置 */
    ngx_pool_t           *next; /* 指向下一個內存池 */
    ngx_uint_t            failed;/* 記錄內存池內存分配失敗的次數 */
} ngx_pool_data_t;  /* 維護內存池的數據塊 */


struct ngx_pool_s {/* 內存池的管理模塊,即內存池頭部結構 */
    ngx_pool_data_t       d;    /* 內存池的數據塊 */
    size_t                max;  /* 內存池數據塊的最大值 */
    ngx_pool_t           *current;/* 指向當前內存池 */
    ngx_chain_t          *chain;/* 指向一個 ngx_chain_t 結構 */
    ngx_pool_large_t     *large;/* 大塊內存鏈表,即分配空間超過 max 的內存 */
    ngx_pool_cleanup_t   *cleanup;/* 析構函數,釋放內存池 */
    ngx_log_t            *log;/* 內存分配相關的日誌信息 */
};
/* 文件 core/ngx_core.h */
typedef struct ngx_pool_s   ngx_pool_t;
typedef struct ngx_chain_s  ngx_chain_t;

緩衝區數據類型

緩衝區 ngx_buf_t 的定義如下:

/* 緩衝區結構 */
typedef void *            ngx_buf_tag_t;

typedef struct ngx_buf_s  ngx_buf_t;

struct ngx_buf_s {
    u_char          *pos;   /* 緩衝區數據在內存的起始位置 */
    u_char          *last;  /* 緩衝區數據在內存的結束位置 */
    /* 這兩個參數是處理文件時使用,類似於緩衝區的pos, last */
    off_t            file_pos;
    off_t            file_last;

    /* 由於實際數據可能被包含在多個緩衝區中,則緩衝區的start和end指向
     * 這塊內存的開始地址和結束地址,
     * 而pos和last是指向本緩衝區實際包含的數據的開始和結尾
     */
    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;          /* 指向buffer對應的文件對象 */
    /* 當前緩衝區的一個影子緩衝區,即當一個緩衝區複製另一個緩衝區的數據,
     * 就會發生相互指向對方的shadow指針
     */
    ngx_buf_t       *shadow;


    /* 爲1時,表示該buf所包含的內容在用戶創建的內存塊中
     * 可以被filter處理變更
     */
    /* the buf's content could be changed */
    unsigned         temporary:1;

    /* 爲1時,表示該buf所包含的內容在內存中,不能被filter處理變更 */
    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* 爲1時,表示該buf所包含的內容在內存中,
     * 可通過mmap把文件映射到內存中,不能被filter處理變更 */
    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    /* 可回收,即這些buf可被釋放 */
    unsigned         recycled:1;
    unsigned         in_file:1; /* 表示buf所包含的內容在文件中 */
    unsigned         flush:1;   /* 刷新緩衝區 */
    unsigned         sync:1;    /* 同步方式 */
    unsigned         last_buf:1;/* 當前待處理的是最後一塊緩衝區 */
    unsigned         last_in_chain:1;/* 在當前的chain裏面,該buf是最後一個,但不一定是last_buf */

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    /* STUB */ int   num;
};

chain 數據類型

ngx_chain_t 數據類型是與緩衝區類型 ngx_buf_t 相關的鏈表結構,定義如下:

struct ngx_chain_s {
    ngx_buf_t    *buf;  /* 指向當前緩衝區 */
    ngx_chain_t  *next; /* 指向下一個chain,形成chain鏈表 */
};
typedef struct {

鏈表圖如下:



參考資料:

《深入理解 Nginx 》

Nginx 從入門到精通

Nginx 代碼研究

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章