nginx之queue的具体使用


Posted in Servers onJune 28, 2022

一、简介

​ nginx队列和linux内核中的链表有一样的结构,只有一个连接头(只有两个指针),任何包含这个结构的数据都可以连接在一起。有点像物联网,万物互联,只要能上网都可以连接。

​ nginx队列是带头节点的一个双向链表。

二、数据结构

typedef struct ngx_queue_s  ngx_queue_t;

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

nginx之queue的具体使用

三、相关API

3.1 初始化一个队列

#define ngx_queue_init(q)                                                     \
    (q)->prev = q;                                                            \
    (q)->next = q

nginx之queue的具体使用

3.2 判断队列是否为空

只有一个头节点,则为空。有头节点的双向链表相比无头的双向链表,各种插入、删除等操作都更简单。

#define ngx_queue_empty(h)                                                    \
    (h == (h)->prev)

3.3 队头插入节点

#define ngx_queue_insert_head(h, x)                                           \
    (x)->next = (h)->next;                                                    \
    (x)->next->prev = x;                                                      \
    (x)->prev = h;                                                            \
    (h)->next = x

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

头部插入节点后

nginx之queue的具体使用

3.4 队尾插入节点

#define ngx_queue_insert_tail(h, x)                                           \
    (x)->prev = (h)->prev;                                                    \
    (x)->prev->next = x;                                                      \
    (x)->next = h;                                                            \
    (h)->prev = x

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

尾部插入节点后

nginx之queue的具体使用

3.5 从队列中移除某个节点

#define ngx_queue_remove(x)                                                   \
    (x)->next->prev = (x)->prev;                                              \
    (x)->prev->next = (x)->next

nginx之queue的具体使用

nginx之queue的具体使用

移除x节点后

nginx之queue的具体使用

可以看到移除节点x后,x和队列还有一定的联系,所以对x的操作一定要小心,不然可能将整个队列损坏。 一般将x->prev,x->next都置空。

3.6 将队列从某个节点拆分成两个队列

#define ngx_queue_split(h, q, n)                                              \
    (n)->prev = (h)->prev;                                                    \
    (n)->prev->next = n;                                                      \
    (n)->next = q;                                                            \
    (h)->prev = (q)->prev;                                                    \
    (h)->prev->next = h;                                                      \
    (q)->prev = n;

将队列h从节点q拆分为h和n两个队列,并且q节点在n队列中。

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

拆分完后

nginx之queue的具体使用

3.7 将两个队列合并成一个队列

#define ngx_queue_add(h, n)                                                   \
    (h)->prev->next = (n)->next;                                              \
    (n)->next->prev = (h)->prev;                                              \
    (h)->prev = (n)->prev;                                                    \
    (h)->prev->next = h;

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

nginx之queue的具体使用

合并后

nginx之queue的具体使用

3.8 队列排序

#define ngx_queue_head(h)                                                     \
    (h)->next


#define ngx_queue_last(h)                                                     \
    (h)->prev


#define ngx_queue_sentinel(h)                                                 \
    (h)


#define ngx_queue_next(q)                                                     \
    (q)->next


#define ngx_queue_prev(q)                                                     \
    (q)->prev
#define ngx_queue_insert_after ngx_queue_insert_head

使用标准的插入排序算法,通过传递的回调函数cmp进行比较,将整个队列排序。

void
ngx_queue_sort(ngx_queue_t *queue,
    ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
{
    ngx_queue_t  *q, *prev, *next;

    q = ngx_queue_head(queue);

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

    for (q = ngx_queue_next(q); q != ngx_queue_sentinel(queue); q = next) {

        prev = ngx_queue_prev(q);
        next = ngx_queue_next(q);

        ngx_queue_remove(q);

        do {
            if (cmp(prev, q) <= 0) {
                break;
            }

            prev = ngx_queue_prev(prev);

        } while (prev != ngx_queue_sentinel(queue));

        ngx_queue_insert_after(prev, q);
    }
}

3.9 获取队列中间节点

通过快慢指针的方式获取中间节点。

ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{
    ngx_queue_t  *middle, *next;

    middle = ngx_queue_head(queue);

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

    next = ngx_queue_head(queue);

    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;
        }
    }
}

3.10 获取原始数据

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

从队列中获取的节点类型都是ngx_queue_s,而不是实际的数据类型,需要将ngx_queue_s转换为原始的类型。其中offsetof是一个内置的表达式,计算某个成员变量在类型中的偏移量。
通过偏移计算到计算到原始类型地址,然后进行类型强转获取原始类型。
比如如下调用

q = ngx_queue_last(&cache->expire_queue);
file = ngx_queue_data(q, ngx_cached_open_file_t, queue);

nginx之queue的具体使用

q的地址减去offset获取到ngx_cached_open_file_t的地址,然后在强转为对应的类型。

到此这篇关于nginx之queue的具体使用的文章就介绍到这了,更多相关nginx queue内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Servers 相关文章推荐
基于nginx实现上游服务器动态自动上下线无需reload的实现方法
Mar 31 Servers
Nginx服务器添加Systemd自定义服务过程解析
Mar 31 Servers
nginx反向代理配置去除前缀案例教程
Jul 26 Servers
Nginx使用Lua模块实现WAF的原理解析
Sep 04 Servers
解决使用了nginx获取IP地址都是127.0.0.1 的问题
Sep 25 Servers
nginx从安装到配置详细说明(安装,安全配置,防盗链,动静分离,配置 HTTPS,性能优化)
Feb 12 Servers
Windows Server 2022 超融合部署(图文教程)
Jun 25 Servers
Python安装及建立虚拟环境的完整步骤
Jun 25 Servers
GPU服务器的多用户配置方法
Jul 07 Servers
Apache Kafka 分区重分配的实现原理解析
Jul 15 Servers
zabbix如何添加监控主机和自定义监控项
Aug 14 Servers
nginx sticky实现基于cookie负载均衡示例详解
Dec 24 Servers
nginx之内存池的实现
vscode远程免密登入Linux服务器的配置方法
vscode内网访问服务器的方法
云服务器部署 Web 项目的实现步骤
在虚拟机中安装windows server 2008的图文教程
腾讯云服务器部署前后分离项目之前端部署
Jun 28 #Servers
windows系统安装配置nginx环境
Jun 28 #Servers
You might like
JS调用CS里的带参方法实例
2013/08/01 Javascript
jQuery 中国省市两级联动选择附图
2014/05/14 Javascript
javascript中函数作为参数调用的方法
2015/02/09 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
D3.js实现文本的换行详解
2016/10/14 Javascript
Bootstrap基本插件学习笔记之折叠(22)
2016/12/08 Javascript
JavaScript获取当前时间向前推三个月的方法示例
2017/02/04 Javascript
Angular中实现树形结构视图实例代码
2017/05/05 Javascript
Thinkjs3新手入门之如何使用静态资源目录
2017/12/06 Javascript
Vue微信项目按需授权登录策略实践思路详解
2018/05/07 Javascript
vue 项目接口管理的实现
2019/01/17 Javascript
微信小程序简单的canvas裁剪图片功能详解
2019/07/12 Javascript
Moment.js实现多个同时倒计时
2019/08/26 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
React.js组件实现拖拽排序组件功能过程解析
2020/04/27 Javascript
JS 设计模式之:工厂模式定义与实现方法浅析
2020/05/06 Javascript
vue基础知识--axios合并请求和slot
2020/06/04 Javascript
ant design 日期格式化的实现
2020/10/27 Javascript
[48:56]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 VG vs KG
2018/03/31 DOTA
python发腾讯微博代码分享
2014/01/10 Python
python复制文件到指定目录的实例
2018/04/27 Python
Python pycharm 同时加载多个项目的方法
2019/01/17 Python
HTML5 使用 sessionStorage 进行页面传值的方法
2018/07/02 HTML / CSS
摩托车和ATV零件、配件和服装的首选在线零售商:MotoSport
2017/12/22 全球购物
Clarria化妆品官方网站:购买天然和有机化妆品系列
2018/04/08 全球购物
金融专业个人的自我评价
2013/10/18 职场文书
小学教师自我鉴定
2013/11/07 职场文书
人民调解员先进事迹材料
2014/05/08 职场文书
落实八项规定专题民主生活会对照检查材料
2014/09/15 职场文书
授权收款委托书范本
2014/10/10 职场文书
承诺书范本大全
2015/05/04 职场文书
工作感想范文
2015/08/07 职场文书
python实现web邮箱扫描的示例(附源码)
2021/03/30 Python
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
2022/02/12 Redis
面试分析分布式架构Redis热点key大Value解决方案
2022/03/13 Redis
pycharm无法安装cv2模块问题
2022/05/20 Python