nginx链表

       nginx服务器接收到客户端的http请求头部时,或者nginx发送响应头部给客户端,这些头部字段都会保存到链表数组中。例如:content_type:text/html。内存布局如下图所示。


图:http头部链表

一、链表结构

//链表头结点
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;
//链表数组结点
struct ngx_list_part_s 
{
    void             *elts;		//数组首地址
    ngx_uint_t        nelts;	//数组中有效元素个数
    ngx_list_part_t  *next;		//指向下一个链表节点
};
链表所有节点都是通过next指针连接起来。而每一个链表节点的元素是一个数组,数组个数以及每个数组元素大小由链表表头节点中的nalloc与size决定。

二、创建链表

通过ngx_list_create函数可以创建一个链表。可以指定链表数组的大小以及每个数组元素的大小

1、创建一个链表表头

2、为链表第一个节点开辟数组空间、

3、保存数组元素的大小以及数组大小

//创建一个链表头,链表首节点数组有n个元素,每个元素为size大小
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;
    }

	//为链表首节点开辟数组空间
    list->part.elts = ngx_palloc(pool, n * size);
    if (list->part.elts == NULL)
	{
        return NULL;
    }

	//链表元素个数为0,表示没有空间被使用,是一个空链表
    list->part.nelts = 0;
    list->part.next = NULL;
	//将链表连接起来
    list->last = &list->part;
	//保存数组元素个数以及每个数组元素大小
    list->size = size;
    list->nalloc = n;
    list->pool = pool;

    return list;
}
三、初始化链表

初始化一个链表和创建链表的操作基本相同,唯一的差别是初始化链表不需要创建链表头,因为调用者已经创建好了

//初始化一个链表,链表首节点数组有n个元素,每个元素为size大小
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;
    }

	//链表元素个数为0,表示没有空间被使用,是一个空链表
    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_push函数。函数的返回值就是数组元素,得到这个元素后,就可以对这个元素进行赋值了。

这个跟我们平时使用的链表过程有点不一样。通常我们都是创建一个链表节点,然后对链表节点进行赋值,之后才把链表节点插入到链表中。

而nginx是预先开辟了链表数组节点,要使用时直接获取就可以了。

//从链表尾节点数组中获取一个元素;
//如果链表没有空间了,则创建一个链表数组节点,并插入到链表末尾
//返回值: 链表数组元素
void * ngx_list_push(ngx_list_t *l)
{
    void             *elt;
    ngx_list_part_t  *last;

    last = l->last;

	//链表没有空间了,则重新创建一个链表数组节点
    if (last->nelts == l->nalloc) 
	{
		//创建链表节点
        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;
}
最终,链表可能的内存布局如下:

图:链表数组内存布局


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值