Nginx源码初探之数据结构 - 队列数据结构

本文深入解析Nginx中的队列数据结构,包括其轻量级链表实现方式,以及如何通过循环和双链表进行节点管理和中间节点获取。介绍了ngx_queue_t类型及其操作,展示了Nginx对Linux系统链表特性的借鉴。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

队列介绍

       队列是有序集合,先进先出FIFO,队列的概念很好理解,队列的应用也非常广泛如:循环队列、阻塞队列、并发队列、优先级队列等。Nginx数据结构是循环队列,prev前置节点环和next后置节点环。

       Nginx链表还是非常有特色的,它是一种轻量级链表,这种链表不包含数据内容,只包含前后节点指针。在使用的时候需要作为带有节点变量的结构体(宿主)的成员变量存在(寄宿链表)。这个结构并非Nginx独有,比如Linux操作系统的链表

1.数据结构

typedef struct ngx_queue_s  ngx_queue_t;

struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};

2.操作

        ngx_queue_t是轻量级链表操作非常好理解,就是维护节点关系,保证双链表结构。这些和关于双链表的基本操作是相同的,Nginx代码很清晰可自行查看。

2.1获取节点内容
根据寄宿链表获取节点内容的原理来获取ngx_queue_t的内容:
1.宿主结构体本身看做一个连续的内存区域
2.利用offsetof宏计算出寄宿链表成员变量相对于结构体起始位置的偏移量
3.寄宿链表的起始地址-寄宿链表成员变量相对于结构体起始位置的偏移量=结构体的起始位置

#define ngx_queue_data(q, type, link)                                         \
    (type *) ((u_char *) q - offsetof(type, link))

2.2获取中间节点
这是个很机巧的问题,双路遍历,移动速度相差一倍,速度快的指针到达末尾时,速度慢的就在中间位置。

ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{
    ngx_queue_t  *middle, *next;
     /*1.首尾相等,只有一个节点直接返回*/
    middle = ngx_queue_head(queue);

    if (middle == ngx_queue_last(queue)) {
        return middle;
    }

    next = ngx_queue_head(queue);
    /*2.双路遍历,middle遍历用于获取中间节点,next遍历用于寻找last节点。由于next遍历是middle遍历的2倍,所以当next遍历到last节点时,middle遍历到中间节点*/
    for ( ;; ) {
        middle = ngx_queue_next(middle);

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }
    }
}

     Nginx的队列吸取了Linux系统的很多特点,具有轻量级,速度快的特点。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值