Nginx单向链表 ngx_list_t
目录
基本概述
数据结构
接口描述
具体实现
ngx_list_create
ngx_list_init
ngx_list_push
使用案例
整理自 nginx 1.9.2 源码 和 《深入理解 Nginx:模块开发与架构解析》
基本概述
Nginx 中的 ngx_list_t 是一个单向链表容器,链表中的每一个节点同时又是数据数组。ngx_list_t 作为链表容器,确定了 ngx_list_part_s 节点的存储空间容量、内存管理入口(内存池)和数据访问入口(链表+数组)。
ngx_list_t 链表具体结构如下图所示。可灵活定义 ngx_list_part_s 中数据结构,同时因为其内部存储地址连续,可通过数组偏移进行快速访问。

数据结构
typedef struct ngx_list_part_s ngx_list_part_t; /*链表中的一个节点,该节点中的 elts 记录一个数组的数据,数组类型可以自定义 ;节点使用的数组,容量(成员个数)已经固定(由 ngx_list_t 中的 nalloc 确定),使用 nelts 记录该数组已使用容量,所以 nelts 肯定小于 nalloc
*/
struct ngx_list_part_s { void *elts; // 指向数组的起始地址。ngx_uint_t nelts; // 数组已使用了多少个元素ngx_list_part_t *next; // 下一个链表节点
};/*ngx_list_part_s 链表容器,该结构体内确定了 ngx_list_part_s 的存储空间容量、内存管理入口和访问入口。
*/
typedef struct { ngx_list_part_t *last; //指向链表的最后一个节点。ngx_list_part_t part; //链表的首个数组节点。// 限制 ngx_list_part_s elts 中每个数组元素的占用空间的大小size_t size; // 限制 ngx_list_part_s elts 中每个数组最大元素数量,一旦分配后是不可更改的ngx_uint_t nalloc;// //链表中管理内存分配的内存池对象。用户要存放的数据占用的内存都是由 pool 分配的。ngx_pool_t *pool;
} ngx_list_t;
接口描述
// 创建新的链表,指定内存池对象,和数组容量(元素个数和每个元素大小)
// 该函数调用后会返回一个链表,该链表内至少有一个数组,不会是空链表的
ngx_list_t *ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size);// 初始化已有链表,与 ngx_list_create 使用方法相似,其实 ngx_list_create 里面也会调用 ngx_list_init
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)// 往链表中新增元素,传入链表,返回新元素的首地址供使用。注意此时返回的是 ngx_list_part_s 中的 elts 成员
void *ngx_list_push(ngx_list_t *list);
具体实现
ngx_list_create
ngx_list_t *
ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size) //实际上就是为nginx_list_t的part成员创建指定的n*size空间,并且创建了空间sizeof(ngx_list_t)
{ngx_list_t *list;// 分配 ngx_list_t 大小的内存list = ngx_palloc(pool, sizeof(ngx_list_t));if (list == NULL) {return NULL;}// 对空链表进行初始化if (ngx_list_init(list, pool, n, size) != NGX_OK) {return NULL;}return list;
}
ngx_list_init
static ngx_inline ngx_int_t
ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{// 对链表的首个 ngx_list_part_s 元素中的数组分配内存,大小为 n * size,n 为数组元素个数,size 为数组内每个元素的大小,我们可以看到,这些配置在链表初始化的时候就已经写死了,不可再改变,除非再次初始化list->part.elts = ngx_palloc(pool, n * size); if (list->part.elts == NULL) {return NGX_ERROR;}// 对链表的一些属性进行赋值list->part.nelts = 0;list->part.next = NULL;// 初始化时,链表只有一个节点,所以首节点也是末尾节点list->last = &list->part;list->size = size;list->nalloc = n;list->pool = pool;return NGX_OK;
}
ngx_list_push
// 往链表的末尾节点中新增数组,函数返回可用地址指针
void *
ngx_list_push(ngx_list_t *l)
{void *elt;ngx_list_part_t *last;last = l->last;// 判断末尾节点的数组空间是否满了if (last->nelts == l->nalloc) {/* the last part is full, allocate a new list part */// 若末尾节点空间满了,则往链表中新增节点,刷新末尾节点地址last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));if (last == NULL) {return NULL;}last->elts = ngx_palloc(l->pool, l->nalloc * l->size);if (last->elts == NULL) {return NULL;}// 新的末尾节点last->nelts = 0;last->next = NULL;// 刷新末尾节点指针,新节点变为末尾节点l->last->next = last;l->last = last;}elt = (char *) last->elts + l->size * last->nelts;last->nelts++;return elt;
}
使用案例
// 创建一个链表,链表中每个数组长度限制为 4,每个数组元素数据类型为 ngx_str_t
// 创建链表的时候,内部会调用 ngx_list_init
ngx_list_t* testlist = ngx_list_create(r->pool, 4, sizeof(ngx_str_t));
if (testlist == null )
{return NGX_ERORR;
}// 往链表中添加数据,该数据会添加到链表末尾节点的数组中,若该数组剩余容量不足,会往链表中新增节点
ngx_str_t* str = ngx_list_push(testlist);
if ( str == null )
{return NGX_ERROR;
}
str->len = sizeof("hello world");
str->value = "he11o world";// 遍历链表
// part 用于指向链表中的每一个 ngx_list_part_t 数组,刚开始执行链表中第一个节点
ngx_list_part_t* part = &testlist.part;
//根据链表中的数据类型,把数组里的 elts 转化为该类型使用
ngx_str_t* str = part->elts;
// i 表示元素在链表的每个 ngx_list_part_t 数组里的序号
for (i ; 0; /* void */; i++)
{// 如果数组已使用的数组元素已经遍历完,则需要跳转到链表中下一个节点if ( i >= part->nelts ){if ( part -> next == NULL ){// 如果某个 ngx_list_part_t 数组的 next 指针为空// 则说明已经遍历完链表了break;}// 访问下一个 ngx_list_part_tpart = part->next;header = part->elts;// 将 i 序号置为 0,准备重新访问下一个数组i = 0;}// 遍历每个链表节点数组内的元素printf("list element : %*s\n", str[i].len, str[i].data);
}
------------------------------------以下为废话,不需要再阅读------------------------------------------
NGINX是一款高性能的HTTP服务器和反向代理服务器,它以其稳定性、丰富的功能集、以及轻量级架构而闻名。在互联网技术栈中,NGINX扮演着至关重要的角色,广泛应用于负载均衡、静态内容服务以及作为反向代理来提高应用的可用性和扩展性。它的事件驱动架构使其能够支持高并发连接,处理大量请求而不显著增加延迟。
NGINX的配置文件采用简洁明了的语法,使得用户可以轻松地进行性能调优和功能定制。通过模块化设计,NGINX不仅支持HTTP/2协议,还提供了对TLS/SSL的全面支持,确保数据传输的安全性。此外,它还具备WebSocket支持,使得实时通信应用能够无缝运行。
NGINX的反向代理能力尤为突出,它可以根据URL路径、头部信息等多种规则将客户端请求智能地转发到后端服务器群中的某一台或多台服务器上,实现请求的高效分发。同时,NGINX还支持健康检查机制,能够自动剔除故障节点,保证服务的高可用性。
对于静态内容的高效处理也是NGINX的一大亮点。它可以快速响应并交付HTML页面、图片、CSS文件等静态资源,极大地提升了网站访问速度。结合其缓存机制,NGINX能有效减轻后端服务器的压力,优化整体系统性能。
NGINX还提供了丰富的第三方模块,如安全防护、流量控制等,进一步增强了其功能性。无论是小型网站还是大型企业级应用,NGINX都能提供灵活且强大的解决方案,是现代Web架构中不可或缺的组成部分。
NGINX是一款高性能的HTTP服务器和反向代理服务器,它以其稳定性、丰富的功能集、以及轻量级架构而闻名。在互联网技术栈中,NGINX扮演着至关重要的角色,广泛应用于负载均衡、静态内容服务以及作为反向代理来提高应用的可用性和扩展性。它的事件驱动架构使其能够支持高并发连接,处理大量请求而不显著增加延迟。
NGINX的配置文件采用简洁明了的语法,使得用户可以轻松地进行性能调优和功能定制。通过模块化设计,NGINX不仅支持HTTP/2协议,还提供了对TLS/SSL的全面支持,确保数据传输的安全性。此外,它还具备WebSocket支持,使得实时通信应用能够无缝运行。
NGINX的反向代理能力尤为突出,它可以根据URL路径、头部信息等多种规则将客户端请求智能地转发到后端服务器群中的某一台或多台服务器上,实现请求的高效分发。同时,NGINX还支持健康检查机制,能够自动剔除故障节点,保证服务的高可用性。
对于静态内容的高效处理也是NGINX的一大亮点。它可以快速响应并交付HTML页面、图片、CSS文件等静态资源,极大地提升了网站访问速度。结合其缓存机制,NGINX能有效减轻后端服务器的压力,优化整体系统性能。
NGINX还提供了丰富的第三方模块,如安全防护、流量控制等,进一步增强了其功能性。无论是小型网站还是大型企业级应用,NGINX都能提供灵活且强大的解决方案,是现代Web架构中不可或缺的组成部分。
相关文章:
Nginx单向链表 ngx_list_t
目录 基本概述 数据结构 接口描述 具体实现 ngx_list_create ngx_list_init ngx_list_push 使用案例 整理自 nginx 1.9.2 源码 和 《深入理解 Nginx:模块开发与架构解析》 基本概述 Nginx 中的 ngx_list_t 是一个单向链表容器,链表中的每一个节…...
go语言中的字符串详解
目录 字符串的基本特点 1.字符串的不可变性 2.其他基本特点 字符串基本操作 1. 创建字符串 2. 获取字符串长度 3. 字符串拼接 4. 遍历字符串 5. 字符串比较 字符串常用函数 1. 判断子串 2. 查找与索引 3. 字符串替换 4. 分割与连接 5. 修剪字符串 6. 大小写转换…...
Windows脚本清理C盘缓存
方法一:使用power文件.ps1的文件 脚本功能 清理临时文件夹: 当前用户的临时文件夹(%Temp%)。系统临时文件夹(C:\Windows\Temp)。 清理 Windows 更新缓存: 删除 Windows 更新下载缓存࿰…...
分布式协同 - 分布式事务_2PC 3PC解决方案
文章目录 导图Pre2PC(Two-Phase Commit)协议准备阶段提交阶段情况 1:只要有一个事务参与者反馈未就绪(no ready),事务协调者就会回滚事务情况 2:当所有事务参与者均反馈就绪(ready&a…...
永磁同步电机负载估计算法--自适应扩张状态观测器
一、 原理介绍 在线性扩张观测器中,LESO观测器增益ω0 决定了观测器的跟踪速度,ω0 越大,观测器估计精度越高, 抗干扰能力越强,瞬态响应速度加快,过大则会引入高频噪声使系统不稳定。为使观测器在全速域内…...
【HarmonyOS应用开发——ArkTS语言】购物商城的实现【合集】
目录 😋环境配置:华为HarmonyOS开发者 📺演示效果: 📖实验步骤及方法: 1. 在src/main/ets文件中创建components文件夹并在其中创建Home.ets和HomeProduct.ets文件。 2. 在Home.ets文件中定义 Home 组…...
Python二维码生成器qrcode库
要在Python中生成二维码,你可以使用 qrcode 库。这个库非常方便,允许你生成并保存二维码图像。下面是一个简单的示例,展示了如何使用 qrcode 库生成二维码。 首先,你需要安装 qrcode 库。你可以使用 pip 来安装它: s…...
Python:模拟(包含例题:饮料换购 图像模糊 螺旋矩阵)
模拟题:直接按照题目含义模拟即可,一般不涉及算法 注意: 1.读懂题:理清楚题目流程 2.代码和步骤一一对应:变量名,函数名,函数功能 3.提取重复的部分,写成对应的函数(…...
git分支与部署环境的关系以及开发规范
一 某金融机构 1.1 分支分类以及作用 1.master master分支为主分支,用于部署生产环境的分支,无论任何时候都要确保master分支的稳定性;master分支由feature及hotfix分支合并,任何时间都不能直接修改代码。目前用于老仿真和老生产,暂时不动。 2.prod 主分支,是master…...
2024最新鸿蒙开发面试题合集(一)-HarmonyOS NEXT Release(API 12 Release)
1. HarmonyOS应用打包后的文件扩展名是? 打包后的文件扩展名为.hap(HarmonyOS Ability Package),这是HarmonyOS应用的标准包格式 2. 页面和自定义组件生命周期有哪些? 页面和自定义组件生命周期说明 有Entry装饰器的component组件的生命…...
【mybatis】详解 # 和 $ 的区别,两者分别适用于哪种场景,使用 $ 不当会造成什么影响
# 和 $ 的区别 在MyBatis中,# 和 $ 是用来处理参数的两种不同方式,它们之间有一些重要的区别: # 符号: # 是用来进行参数占位符的,它会进行 SQL 注入防护。使用 # 时,MyBatis 会将参数值进行预处理&…...
Java面试题,数据结构,图的最短路径算法应用于社交网络分析
图的最短路径算法应用于社交网络分析 在一个大型社交网络中,用户想要找到连接两个特定用户的最短路径。假设你已经有了这个社交网络的数据模型,其中节点代表用户,边代表用户之间的关系。请设计一个解决方案,以找出两个用户之间的…...
Tree数据处理
文章目录 一、Tree数据重置二、Tree拆分成二级数据1、过滤数据2、二级数据 Tree组件的数据处理往往需要使用递归,本文归纳一下常见的数据处理情景,持续更新; 一、Tree数据重置 递归的标志就是寻找子元素的集合字段,一般为children…...
idea配置gitee仓库
idea配置gitee 0、fork开源项目 到自己的仓库,这一步相当于创建了一个自己的git仓库,并复制了别人的开源代码。 注意:如果直接下载别人的开源项目,需要从新配置git仓库信息,因为开源项目一般都设置了git信息。而修改…...
SpringBoot 事务
事务是一组操作的集合, 是一个不可分割的操作.会把所有的操作作为一个整体, 一起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成功, 要么同时失败. 为什么需要事务? 我们在进行程序开发时, 也会有事务的需求. 比如转账操作: 第一步:A 账户 -100 元. …...
我的JAVA-Web基础(1)
1.HTML 2.css CSS(层叠样式表)提供了多种选择器来定位HTML文档中的元素,以便可以应用样式。以下是三种常用的选择器简述: ID 选择器: ID选择器使用HTML元素的id属性来定位单个元素。每个页面中id应该是唯一的…...
【Leetcode 热题 100】207. 课程表
问题背景 你这个学期必须选修 n u m C o u r s e s numCourses numCourses 门课程,记为 0 0 0 到 n u m C o u r s e s − 1 numCourses - 1 numCourses−1。 在选修某些课程之前需要一些先修课程。 先修课程按数组 p r e r e q u i s i t e s prerequisites p…...
从CreateDialogIndirectParam起---我与大模型对话
前言: 对当前的大模型来说,一切皆程序,皆标准。只能按照推定的线路行走,就像机器人走进死胡同,不停的踏步也不回头。除非人为去干预它。其实我提出的这个问题前是因为我不清楚了解一部分WinAPI有着严格的检查机制和自毁…...
重温设计模式--建造者模式
文章目录 建造者模式(Builder Pattern)概述建造者模式UML图作用:建造者模式的结构产品(Product):抽象建造者(Builder):具体建造者(Concrete Builderÿ…...
CSS(五):定位
目录 相对定位 绝对定位 固定定位 在 CSS 中,position 属性用于控制元素的定位方式,使我们可以精确地控制元素在页面上的位置。定位分为相对定位、绝对定位、和固定定位 相对定位 相对定位:position: relative; 相对定位意味着元素的位置…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
