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

相关文章
相关标签/搜索