Nginx源码阅读:ngx_list_t 链表

简介: Nginx源码阅读:ngx_list_t 链表

一、Nginx中链表(ngx_list_t)的结构图

ngx_list_t作为一个链表的结构体,里面是一些链表的信息,ngx_list_part_t是链表的节点。

ngx中的链表并不是将内存简单串起来,而是将内存组织成块(chunck,在ngx中叫part),然后将这些块通过链表串起来。

每个块划分为nalloc片区域,每片区域的大小为size,因此一个chunck的大小为n*nalloc

一个chunck中已分配的区域片数为nelts

二、源码阅读

1、ngx_list_part_s

//一个chunk块(part)
struct ngx_list_part_s {
    void             *elts;  //数据区域首地址的指针
    ngx_uint_t        nelts; //已分配的数据区域的个数
    ngx_list_part_t  *next;  //下一个chunck(part)
};

2、ngx_list_t

链表的结构体,包含一些链表的信息,用于将(chunck)part组织起来

//链表,用来组织chunk块
typedef struct {
    ngx_list_part_t  *last;     //最后一块chunck
    ngx_list_part_t   part;     //第一块chunck
    size_t            size;     //一个片的大小为size(一个chunck分为nalloc片,那么一个chunck大小为nalloc*size)
    ngx_uint_t        nalloc;   //一个chunck划分成nalloc片区域
    ngx_pool_t       *pool;     //所属的内存池
} ngx_list_t;

3、ngx_list_create

创建一个链表,首先要从内存池中分配一块数据给list结构体,然后再交给ngx_list_init去初始化具体信息,和分配数据区域空间。

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));//从内存池分配一块数据,用于存储list结构体
    if (list == NULL) {
        return NULL;
    }
    if (ngx_list_init(list, pool, n, size) != NGX_OK) {//初始化
        return NULL;
    }
    return list;
}

4、ngx_list_init

初始化list结构体的信息,并分配一块chunck

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);//创建一块chunck的数据区域,大小为 片数量*每个片的空间大小
    if (list->part.elts == NULL) {
        return NGX_ERROR;
    }
    list->part.nelts = 0;//初始化的时候,还没将空间使用,因此是0
    list->part.next = NULL;
    list->last = &list->part;//初始化的时候最后一块chunck就是第一块
    list->size = size;//初始化的数据大小
    list->nalloc = n;
    list->pool = pool;//所属的内存池
    return NGX_OK;
}

5、ngx_list_push

通过list来获取一块空间的首地址。

取一块数据为什么叫push呢?因为数据是通过list组织起来的,分配的空间通过list来组织,也就是要push到list中的。

void *
ngx_list_push(ngx_list_t *l)
{
    void             *elt;
    ngx_list_part_t  *last;
    last = l->last;//list中最后一个chunck
    if (last->nelts == l->nalloc) {//如果最后一块chunck中的片已经全部使用完了,那么就要新创建一个chunck,以及空间大小
        /* the last part is full, allocate a new list part */
        last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));//创建chunck头的空间
        if (last == NULL) {
            return NULL;
        }
        last->elts = ngx_palloc(l->pool, l->nalloc * l->size);//创建chunck数据空间
        if (last->elts == NULL) {
            return NULL;
        }
        last->nelts = 0;//已使用的片的数量为0
        last->next = NULL;
        l->last->next = last;//新创建的chunck为最后一个chunk
        l->last = last;
    }
    elt = (char *) last->elts + l->size * last->nelts;//返回可以使用的内存空间地址(根据当前chunck中已经使用的片数量)
    last->nelts++;//当前chunck中使用的片数量+1
    return elt;
}
相关文章
|
6月前
|
应用服务中间件 Linux 网络安全
CentOS 7.4源码编译nginx1.12 并且隐藏nginx的版本
CentOS 7.4源码编译nginx1.12 并且隐藏nginx的版本
119 0
|
16天前
|
存储 Java
HashMap之链表转红黑树(树化 )-treefyBin方法源码解读(所有涉及到的方法均有详细解读,欢迎指正)
本文详细解析了Java HashMap中链表转红黑树的机制,包括树化条件(链表长度达8且数组长度≥64)及转换流程,确保高效处理大量数据。
47 1
|
27天前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
44 2
|
25天前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
16 0
|
2月前
|
负载均衡 网络协议 应用服务中间件
web群集--rocky9.2源码部署nginx1.24的详细过程
Nginx 是一款由 Igor Sysoev 开发的开源高性能 HTTP 服务器和反向代理服务器,自 2004 年发布以来,以其高效、稳定和灵活的特点迅速成为许多网站和应用的首选。本文详细介绍了 Nginx 的核心概念、工作原理及常见使用场景,涵盖高并发处理、反向代理、负载均衡、低内存占用等特点,并提供了安装配置教程,适合开发者参考学习。
|
3月前
|
应用服务中间件 Linux nginx
在CentOS上使用源码包安装Nginx、以及手动启动Nginx的步骤过程
这篇文章介绍了在CentOS系统上使用Nginx源码包进行安装和配置的详细步骤,包括源码包的获取、解压、配置、编译、安装、启动验证以及注意事项。
304 0
在CentOS上使用源码包安装Nginx、以及手动启动Nginx的步骤过程
|
3月前
【数据结构】双向带头(哨兵位)循环链表 —详细讲解(赋源码)
【数据结构】双向带头(哨兵位)循环链表 —详细讲解(赋源码)
89 4
|
3月前
|
存储 测试技术
【初阶数据结构篇】单链表的实现(附源码)
在尾插/尾删中,都需要依据链表是否为空/链表是否多于一个节点来分情况讨论,目的是避免对空指针进行解引用造成的错误。
36 0
|
4月前
|
存储 C++
C++的list-map链表与映射表
```markdown C++ 中的`list`和`map`提供链表和映射表功能。`list`是双向链表,支持头尾插入删除(`push_front/push_back/pop_front/pop_back`),迭代器遍历及任意位置插入删除。`map`是键值对集合,自动按键排序,支持直接通过键来添加、修改和删除元素。两者均能使用范围for循环遍历,`map`的`count`函数用于统计键值出现次数。 ```
34 1
|
5月前
|
存储 C++
C++的list-map链表与映射表
这篇教程介绍了C++中`list`链表和`map`映射表的基本使用。`list`链表可通过`push_front()`、`push_back()`、`pop_front()`和`pop_back()`进行元素的添加和删除,使用迭代器遍历并支持在任意位置插入或删除元素。`map`是一个键值对的集合,元素自动按键值排序,可使用下标操作符或`insert()`函数插入元素,通过迭代器遍历并修改键值对,同时提供`count()`方法统计键值出现次数。教程中包含多个示例代码以帮助理解和学习。
45 2