nginx代碼分析-基本結構-單鏈表ngx_list_t

一.數據結構數組

單向鏈表, 每一個鏈表數據節點實際是一個數組, 數組總長度一致, 數組元素大小一致.數據結構

ngx_list_t爲鏈表頭節點, 定義了鏈表數據節點數組中數據元素大小(size), 每一個節點最大的數據個數(nalloc), 以及一個last指針指向鏈表的尾部數據節點方便插入數據操做.函數

ngx_list_part_t爲鏈表數據節點, 記錄了當前數組中已佔用元素的個數, next指針指向下一節點.ui

struct ngx_list_part_s { void             *elts;   // 實際數據, n * size
    ngx_uint_t        nelts;  // 節點數組已經使用的元素個數
    ngx_list_part_t  *next;   // 鏈表next指針
}; 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;

二.鏈表的建立spa

ngx_list_t * ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size) { ngx_list_t *list; list = ngx_palloc(pool, sizeof(ngx_list_t)); // 分配鏈表頭
    if (list == NULL) { return NULL; } if (ngx_list_init(list, pool, n, size) != NGX_OK) { return NULL; } return list; } static ngx_inline ngx_int_t ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size) { // 初始化鏈表
    list->part.elts = ngx_palloc(pool, n * size); // 爲頭結點分配n*size大小的數據空間
    if (list->part.elts == NULL) { return NGX_ERROR; } list->part.nelts = 0; list->part.next = NULL; list->last = &list->part; list->size = size; list->nalloc = n; list->pool = pool; return NGX_OK; }

如圖爲初始化後鏈表結構, 首先在內存池ngx_pool_t中分配鏈表頭ngx_list_t的空間, 再經過ngx_list_init函數分配鏈表頭數據節點的空間, 大小爲nalloc * size..net

 

image 

三.鏈表的使用指針

void * ngx_list_push(ngx_list_t *l) { void             *elt; ngx_list_part_t *last; last = l->last; if (last->nelts == l->nalloc) { // 尾節點數組元素分配達到上限

        /* the last part is full, allocate a new list part */ last = ngx_palloc(l->pool, sizeof(ngx_list_part_t)); if (last == NULL) { // 建立鏈表數據節點頭
            return NULL; } last->elts = ngx_palloc(l->pool, l->nalloc * l->size); if (last->elts == NULL) { // 建立鏈表數據節點數據空間
            return NULL; } last->nelts = 0; last->next = NULL; l->last->next = last;  // 數據節點加入末尾
        l->last = last;     // 鏈表頭指向尾數據節點
 } elt = (char *) last->elts + l->size * last->nelts; last->nelts++; // 返回一個元素
    return elt; }

對於已創建的鏈表, ngx_list_push返回1個新元素的內存地址. 經過鏈表頭的last指針找到鏈表尾節點, 若是elts中還有空間則分配一個元素, 不然新建一個鏈表數據節點ngx_list_part_t, 在新節點中分配,頭結點指向該新節點code

image

相關文章
相關標籤/搜索