ngx_list_init
定义 在 src\core\ngx_list.h
c
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);
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_list_init
是 Nginx 中用于初始化链表结构的关键函数
函数签名
c
static ngx_inline ngx_int_t
ngx_list_init(
ngx_list_t *list,
ngx_pool_t *pool,
ngx_uint_t n,
size_t size
);
1. static ngx_inline
-
static
限制函数的作用域为当前编译单元(即当前源文件),防止与其他文件中的同名函数冲突。
-
ngx_inline
Nginx 定义的宏(通常展开为
inline
),提示编译器将函数内联展开,减少函数调用开销。适用于频繁调用的小函数(如初始化、简单操作)。
2. 返回值 ngx_int_t
- 返回值含义 :
NGX_OK
(成功):初始化成功,链表可用。NGX_ERROR
(失败):内存分配失败
3. 参数详解
(1) ngx_list_t *list
- 类型 :指向
ngx_list_t
结构的指针。 - 作用:需要被初始化的链表对象。
(2) ngx_pool_t *pool
- 类型:指向 Nginx 内存池的指针。
- 作用:为链表提供内存分配服务。
- 意义 :
- 所有链表相关的内存(包括初始数据块和后续扩展的数据块)均从该内存池分配。
- 内存池管理简化了内存释放流程(销毁池即可回收所有内存)。
(3) ngx_uint_t n
- 类型 :Nginx 自定义的无符号整型(
typedef unsigned int ngx_uint_t
)。 - 作用:指定每个数据块预分配的元素数量。
- 影响 :
- 决定初始内存块的大小为
n * size
。 - 值过大会浪费内存,过小会导致频繁分配新数据块。
- 决定初始内存块的大小为
(4) size_t size
- 类型 :标准库的无符号整型(通常为
unsigned long
)。 - 作用:指定链表中每个元素的大小(字节)。
- 要求 :
- 必须与实际存储的数据类型大小一致(如
sizeof(ngx_table_elt_t)
)。
- 必须与实际存储的数据类型大小一致(如
详解
1. 分配初始内存块
c
list->part.elts = ngx_palloc(pool, n * size);
为链表的第一个数据块分配内存,大小为 n * size
。
ngx_palloc
从 pool
分配内存,返回指针赋给 part.elts
。
2. 检查内存分配结果
c
if (list->part.elts == NULL) {
return NGX_ERROR;
}
验证内存分配是否成功。
内存分配失败会导致后续操作崩溃,需立即返回错误。
若 elts
为 NULL
,说明分配失败,返回 NGX_ERROR
。
3. 初始化当前块元素计数
c
list->part.nelts = 0;
设置当前块已用元素数量为 0。
nelts
(number of elements)记录块内已使用的元素数,初始时未添加元素。
提供计数功能,便于后续判断是否需要分配新块。
4. 初始化当前块的后继指针
c
list->part.next = NULL;
标记当前块为最后一个块,无后续块。
链表初始仅包含一个块,后续块通过 next
指针链接。
5. 设置最后一个块的指针
c
list->last = &list->part;
将 last
指向链表的第一个块(即当前唯一块)。
last
是指向链表最后一个块的指针,用于快速追加元素。
&list->part
获取第一个块的地址,赋给 last
。
通过 last
直接定位到链表尾部,避免遍历整个链表,提升插入效率。
6. 保存元素大小
c
list->size = size;
记录每个元素的大小(字节)。
后续添加元素时需根据 size
计算内存偏移量。
7. 保存预分配元素数量
c
list->nalloc = n;
记录每个块预分配的元素数量。
新块分配时需按 n
预分配内存,平衡内存使用与性能。
控制内存分配粒度,减少碎片化。
8. 关联内存池
c
list->pool = pool;
保存内存池指针,用于后续内存分配。
9. 返回成功状态
c
return NGX_OK;
通知调用者初始化成功。
明确函数执行结果,便于错误处理。