小知识:nginx之queue的具体使用

目录一、简介二、数据结构三、相关API3.1 初始化一个队列3.2 判断队列是否为空3.3 队头插入节点3.4 队尾插入节点3.5 从队列中移除某个节点3.6 将队列从某个节点拆分成两个队列3.7 将两个队列合并成一个队列3.8 队列排序3.9 获取队列中间节点3.10 获取原始数据

一、简介

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的具体使用-1猿站网-插图

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的具体使用-2猿站网-插图

%小知识:nginx之queue的具体使用-3猿站网-插图

%小知识:nginx之queue的具体使用-4猿站网-插图

%小知识:nginx之queue的具体使用-5猿站网-插图

%小知识:nginx之queue的具体使用-6猿站网-插图

头部插入节点后

%小知识:nginx之queue的具体使用-7猿站网-插图

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的具体使用-8猿站网-插图

%小知识:nginx之queue的具体使用-9猿站网-插图

%小知识:nginx之queue的具体使用-10猿站网-插图

%小知识:nginx之queue的具体使用-11猿站网-插图

尾部插入节点后

%小知识:nginx之queue的具体使用-12猿站网-插图

3.5 从队列中移除某个节点

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

%小知识:nginx之queue的具体使用-13猿站网-插图

%小知识:nginx之queue的具体使用-14猿站网-插图

移除x节点后

%小知识:nginx之queue的具体使用-15猿站网-插图

可以看到移除节点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的具体使用-16猿站网-插图

%小知识:nginx之queue的具体使用-17猿站网-插图

%小知识:nginx之queue的具体使用-18猿站网-插图

%小知识:nginx之queue的具体使用-19猿站网-插图

%小知识:nginx之queue的具体使用-20猿站网-插图

%小知识:nginx之queue的具体使用-21猿站网-插图

拆分完后

%小知识:nginx之queue的具体使用-22猿站网-插图

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的具体使用-23猿站网-插图

%小知识:nginx之queue的具体使用-24猿站网-插图

%小知识:nginx之queue的具体使用-25猿站网-插图

%小知识:nginx之queue的具体使用-26猿站网-插图

合并后

%小知识:nginx之queue的具体使用-27猿站网-插图

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的具体使用-28猿站网-插图

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

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

原文地址:https://blog.csdn.net/happytree001/article/details/123949616

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:linux查看服务器开放的端口和启用的端口多种方式

2023-3-20 2:20:57

建站知识

小知识:vsftpd用户禁止ssh登陆的实现方法

2023-3-20 2:29:44

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索