Nginx高效数据结构(3)——队列(ngx_queue_t)

Nginx是我们学习编程的一个非常有参考价值的开源项目。良好的编码风格,高效的数据结构、架构设计。

通常学习Nginx主要有以下两种情形:

1) 需求驱动型。在实际应用中,需要在Nginx的基础上,开发一些特定需求的模块,为此,我们需要去了解Nginx的工作原理、架构设计,并完成相关功能模 块的开发。这种情形下,一个比较好的学习路线是从开发一个简单的“Hello,world” HTTP模块入手,逐步深入。

2)知识驱动型。单纯从学习编程的角度出发,Nginx的模块化设计,架构,高效数据结构设计等都是不可多得的学习资源!这种情形下,通常从学习其常用的数据结构开始是一个不错的选择。

快课网在此搜罗了一些优质资源。从本文开始讲述Nginx中常用的数据结构,主要包括Nginx的数组结构链表结构队列hash结构内存池等。

0. 序

本文继续介绍nginx的数据结构——队列。Nginx的队列由有头节点的双向循环链表实现,具体可参看Linux内核链表实现

链表实现文件:文件:./src/core/ngx_queue.h/.c。.表示nginx-1.0.4代码目录,本文为/usr/src/nginx-1.0.4。

1.队列结构

nginx的队列是由具有头节点的双向循环链表实现的,每一个节点结构为ngx_queue_t,定义如下。

其中,sizeof(ngx_queue_t)=8。

从队列结构定义可以看出,nginx的队列结构里并没有其节点的数据内容。

2. 队列操作

队列有如下操作。

其中,插入节点、取队列头、取队列尾等操作由宏实现,获取中间节点、排序等操作由函数实现。下面简单介绍。

 

2.1 在头节点之后插入

 

在头节点之后插入操作由宏ngx_queue_insert_head完成,如下。

画出该操作的逻辑图,如下。

queue01

图中虚线表示被修改/删除的指针,蓝色表示新修改/增加的指针。下同。

2.2在尾节点之后插入

 

在尾节点之后插入操作由宏ngx_queue_insert_tail完成,如下。

该操作的逻辑图如下。

queue02

2.3 删除节点

在尾节点之后插入操作由宏ngx_queue_remove完成,如下。

该操作的逻辑图如下。

queue03

2.4 分割队列

分割队列操作由宏ngx_queue_split完成,如下。

该宏有3个参数,h为队列头(即链表头指针),将该队列从q节点将队列(链表)分割为两个队列(链表),q之后的节点组成的新队列的头节点为n,图形演示如下。

queue04

2.5 链接队列

链接队列由宏ngx_queue_add完成,操作如下。

其中,h、n分别为两个队列的指针,即头节点指针,该操作将n队列链接在h队列之后。演示图形如下。

queue05

宏ngx_queue_split和ngx_queue_add只在http模块locations相关操作中使用,在后续的讨论http模块locations相关操作时再详细叙述。

2.6 获取中间节点

中间节点,若队列有奇数个(除头节点外)节点,则返回中间的节点;若队列有偶数个节点,则返回后半个队列的第一个节点。操作如下。

为什么该算法能够找到中间节点?

——注意代码中的next指针,其每次均会后移两个位置(节点),而middle指针每次后移一个位置(节点)。演示图形如下。

queue06

2.7 队列排序

队列排序采用的是稳定的简单插入排序方法,即从第一个节点开始遍历,依次将当前节点(q)插入前面已经排好序的队列(链表)中,下面程序中,前面已经排好序的队列的尾节点为prev。操作如下。

该排序操作使用前面介绍的宏来完成其插入动作,只是一些简单的修改指针指向的操作,效率较高。关于该操作的例子,请参考后文的内容。

2.8 如何获取队列节点数据

 

由队列基本结构和以上操作可知,nginx的队列操作只对链表指针进行简单的修改指向操作,并不负责节点数据空间的分配。因此,用户在使用nginx队列时,要自己定义数据结构并分配空间,且在其中包含一个ngx_queue_t的指针或者对象,当需要获取队列节点数据时,使用ngx_queue_data宏,其定义如下。

由该宏定义可以看出,一般定义队列节点结构(该结构类型为type)时,需要将真正的数据放在前面,而ngx_queue_t结构放在后面,故该宏使用减法计算整个节点结构的起始地址(需要进行类型转换)。关于该宏的使用,请参考下文的代码。

 

3. 一个例子

本节给出一个创建内存池并从中分配队列头节点和其他节点组成队列的简单例子。在该例中,队列的数据是一系列的二维点(x,y分别表示该点的横、纵坐标),将这些点插入队列后进行排序,以此向读者展示nginx队列的使用方法。

3.1代码

3.2如何编译

本文编写的makefile文件如下。

3.3 运行结果

该队列的逻辑图如下。

queue07

4. 小结

本文针对nginx-1.0.4的队列进行了较为全面的分析,包括队列结构和队列操作,队列操作主要包括在头节点之后插入节点、在尾节点之后插入节点、获取中间节点、队列排序等。最后通过一个简单例子向读者展示nginx队列的使用方法,同时借此向读者展示编译测试nginx代码的方法。

系列文章:

从开源代码Nginx中学习编码风格

nginx架构初探

Nginx高效数据结构(1)——数组(ngx_array_t)

Nginx高效数据结构(2)——链表(ngx_list_t)

Nginx高效数据结构(3)——队列(ngx_queue_t)

Nginx高效数据结构(4)——Hash表(ngx_hash_t)

Nginx高效数据结构(5)——内存池(ngx_pool_t)

作者:阿波

EDITED BY:快课(www.cricode.com)

本文链接:http://cricode.com/2983.html

转载请保留原始作者信息及本文链接,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值