Nginx源码阅读-队列
前言
这个queue从字面上来说是队列,但是阅读完之后感觉是一个双向循环链表,暂时也不知道怎么称呼了,后续能确定了之后再说吧。
Nginx中的队列也是一个包含哨兵节点的双向循环链表,和我们从教材中认识的双向循环链表有一些不同。在Nginx中,双向循环链表的结构体中只有两个数据成员,分别是指向前一个结构体的指针和指向后一个结构体多的指针,并没有一个数据成员是用来保存数据的。这是因为在Nginx中,队列都是作为其他结构中的一个数据成员出现的,相关数据存储都在和其他结构体中体现的。
数据结构定义
1 | typedef struct ngx_queue_s ngx_queue_t; |
主要方法
ngx_queue_init
初始化
1 |
|
ngx_queue_empty
判断队列是否为空
1 |
|
ngx_queue_insert_head
从队列头部插入
1 |
|
ngx_queue_insert_after
从队列头部插入
1 |
ngx_queue_insert_tail
尾部插入
1 |
|
ngx_queue_head
获取队列第一个元素
1 |
|
ngx_queue_sentinel
获取队列的哨兵元素
1 |
|
ngx_queue_next
获取队列的下一个元素
1 |
|
ngx_queue_prev
获取队列的前一个元素
1 |
|
ngx_queue_remove
从队列中删除元素
1 |
|
ngx_queue_split
1 |
|
ngx_queue_data
获取队列节点对应的数据节点
1 |
|
示例
下面的示例图是结构体ngx_http_file_cache_node_t
的示意图,queue
作为其第二个数据成员,其相对ngx_http_file_cache_node_t
的偏移量就是结构体ngx_rbtree_node_t
大小。因此把queue
的地址减去这个偏移量就得到了ngx_http_file_cache_node_t
的地址了。
拓展
在c语言中offsetof
的作用就是求结构体中某一成员的相对偏移量的,其实现如下,就是把地址0
作为结构体的起始地址,然后获取相应的成员的地址就是我们要的偏移量了。
1 |
ngx_queue_middle
获取队列处于中间位置的节点
1 | ngx_queue_t * |
ngx_queue_sort
队列排序
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);
}
}