ngx_output_chain_get_buf

发布时间:2026/9/15 0:52:12

ngx_output_chain_get_buf 1 定义ngx_output_chain_get_buf 函数 定义在 src/core/ngx_output_chain.cstaticngx_int_tngx_output_chain_get_buf(ngx_output_chain_ctx_t*ctx,off_tbsize){size_tsize;ngx_buf_t*b,*in;ngx_uint_trecycled;inctx-in-buf;sizectx-bufs.size;recycled1;if(in-last_in_chain){if(bsize(off_t)size){/* * allocate a small temp buf for a small last buf * or its small last part */size(size_t)bsize;recycled0;}elseif(!ctx-directioctx-bufs.num1(bsize(off_t)(sizesize/4))){/* * allocate a temp buf that equals to a last buf, * if there is no directio, the last buf size is lesser * than 1.25 of bufs.size and the temp buf is single */size(size_t)bsize;recycled0;}}bngx_calloc_buf(ctx-pool);if(bNULL){returnNGX_ERROR;}if(ctx-directio){/* * allocate block aligned to a disk sector size to enable * userland buffer direct usage conjunctly with directio */b-startngx_pmemalign(ctx-pool,size,(size_t)ctx-alignment);if(b-startNULL){returnNGX_ERROR;}}else{b-startngx_palloc(ctx-pool,size);if(b-startNULL){returnNGX_ERROR;}}b-posb-start;b-lastb-start;b-endb-lastsize;b-temporary1;b-tagctx-tag;b-recycledrecycled;ctx-bufb;ctx-allocated;returnNGX_OK;}2 目的1 设计意图ngx_output_chain_get_buf是ngx_output_chain输出链引擎的内部缓冲区分配器负责在需要拷贝转发而非零拷贝原样转发时按当前上下文需求智能创建一个新的临时缓冲区ngx_buf_t 数据存储空间。3 详解1 函数签名staticngx_int_tngx_output_chain_get_buf(ngx_output_chain_ctx_t*ctx,off_tbsize)1 返回值ngx_int_t返回值值含义NGX_OK0缓冲区分配成功ctx-buf指向新分配的、已初始化的ngx_buf_tctx-allocated已加 1NGX_ERROR-1分配失败内存池耗尽上层应终止处理并向上返回错误2 函数名ngx_output_chain_get_buf词段含义ngxNginx 源码前缀output_chain属于ngx_output_chain输出链子系统get“获取”表示获取一个可用的缓冲区资源buf获取的对象是缓冲区ngx_buf_t3 参数列表参数类型含义来源约束ctxngx_output_chain_ctx_t *输出链上下文维护缓冲区分配计数、配置参数、DirectIO 标志等调用方ngx_output_chain创建并持有非 NULLctx-in必须有效调用点已保证 bszie 0 且非特殊 bufbsizeoff_t即将需要拷贝的源数据量字节由ngx_buf_size(ctx-in-buf)计算得出ngx_output_chain内循环从ctx-in-buf计算必定 0零长度已在调用前的分支中跳过负长度已返回错误2 逻辑流程ngx_output_chain_get_buf(ctx, bsize) ├─ [1] 上下文初始化 │ └─ 获取源 bufctx-in-buf、标准大小ctx-bufs.size、默认标记 recycled1 ├─ [2] 末尾缓冲区尺寸优化in-last_in_chain 为真时触发 │ ├─ [2.1] 数据量小于标准大小 │ │ └─ bsize bufs.size → 缩小为标准大小标记不可回收recycled0 │ ├─ [2.2] 数据量在 1.0x~1.25x 之间 单缓冲区 非 DirectIO │ │ └─ bsize 1.25*bufs.size 且 num1 且 !directio → 精确分配标记不可回收recycled0 │ └─ [2.3] 数据量 1.25x 或多缓冲区或 DirectIO │ └─ 保持标准大小标记可回收recycled1 ├─ [3] 分配缓冲区控制结构ngx_buf_t │ └─ ngx_calloc_buf → 失败返回 NGX_ERROR ├─ [4] 分配数据存储空间 │ ├─ [4.1] DirectIO 路径 │ │ └─ ngx_pmemalign 对齐分配 → 失败返回 NGX_ERROR │ └─ [4.2] 普通路径 │ └─ ngx_palloc 内存池分配 → 失败返回 NGX_ERROR ├─ [5] 初始化缓冲区元数据 │ └─ poslaststart; endstartsize; temporary1; tagctx-tag; recycledrecycled └─ [6] 注册到上下文 └─ ctx-buf b; ctx-allocated; 返回 NGX_OKsize_tsize;ngx_buf_t*b,*in;ngx_uint_trecycled;局部变量声明1 上下文初始化inctx-in-buf;sizectx-bufs.size;recycled1;处理逻辑in ctx-in-buf获取当前待处理的源缓冲区指针。在调用本函数时ctx-in链已确保非空ngx_output_chain主循环的while (ctx-in)保证且bsize 0零长度和负长度已在前面分支处理size ctx-bufs.size获取标准缓冲区大小。该值来自 Nginx 配置指令output_buffers number size中的size参数——决定了每个临时输出缓冲区的默认大小recycled 1默认标记缓冲区为可回收。可回收意味着该缓冲区在发送完毕后会被ngx_chain_update_chains通过tag匹配回收到ctx-free链表中供后续复用这是 Nginx 缓冲区对象池机制的核心ctx-bufs类型ngx_bufs_t定义在src/core/ngx_buf.h:L65-L68typedefstruct{ngx_int_tnum;/* 允许分配的最大缓冲区数量 */size_tsize;/* 每个缓冲区的标准大小字节 */}ngx_bufs_t;2 末尾缓冲区尺寸优化if(in-last_in_chain){if(bsize(off_t)size){/* * allocate a small temp buf for a small last buf * or its small last part */size(size_t)bsize;recycled0;}elseif(!ctx-directioctx-bufs.num1(bsize(off_t)(sizesize/4))){/* * allocate a temp buf that equals to a last buf, * if there is no directio, the last buf size is lesser * than 1.25 of bufs.size and the temp buf is single */size(size_t)bsize;recycled0;}}进入条件in-last_in_chain 1——当前源缓冲区是整个响应体数据链中的最后一块。last_in_chain是ngx_buf_t结构体的位域字段由上游 content handler 在构造最后一个响应数据缓冲区时置位。它告知输出链引擎这是最后一块数据后面不会再追加。设计意图当知道这是最后一块时有机会避免为少量数据分配一个完整大小的缓冲区从而节省内存。该优化分两个子分支。2.1 数据量小于标准大小if(bsize(off_t)size){size(size_t)bsize;recycled0;进入条件bsize ctx-bufs.size——最后一块数据的实际大小不足一个标准缓冲区。处理逻辑size (size_t) bsize将分配大小缩小为实际数据量。例如配置的output_buffers 1 32k最后一块只有 512 字节则分配 512 字节而非 32KB——省下了约 31.5KB 内存recycled 0标记为不可回收。因为 512 字节的缓冲区在下一轮循环中不可能满足标准 32KB 的再分配需求回收它只会浪费 free 链表上的遍历开销和内存碎片场景典型的 HTTP 响应末尾——如 gzip 压缩后最后一块只有几百字节或者 static 模块发送文件时最后一个 buffer 只包含不到一页的数据。2.2 数据量在 1.0x~1.25x 之间}elseif(!ctx-directioctx-bufs.num1(bsize(off_t)(sizesize/4))){size(size_t)bsize;recycled0;}进入条件三个条件同时满足!ctx-directio非 DirectIO 模式。DirectIO 要求缓冲区按磁盘扇区对齐精确大小的缓冲区无法保证对齐因此不适用此优化ctx-bufs.num 1配置只允许分配 1 个缓冲区即output_buffers 1 size。如果num 1说明系统允许同时持有多个缓冲区先分配一个标准大小的更为合理bsize (off_t) (size size / 4)数据量不超过标准大小的 1.25 倍即bsize 1.25 * size。这里的size size / 4是整数运算实现的 1.25 倍阈值处理逻辑size (size_t) bsize精确分配——分配大小恰好等于数据量recycled 0标记为不可回收设计意图为什么要设 1.25 倍阈值这是一个内存节省 vs 回收复用的权衡。对于 1.01x 到 1.25x 的数据量若分配标准大小如 32KB浪费不多但可以回收复用但 Nginx 选择精确分配 不回收因为在num 1的单缓冲区配置下回收链上只有一个条目回收收益极小而稍微减少一点内存分配更有利对于超过 1.25x 的数据量走 [2.3] 分支使用标准大小多次拷贝为什么num 1是必要条件单缓冲区配置意味着allocated上限为 1——刚分配的这个缓冲区被消费后ctx-allocated回到 0下次 再次调用本函数分配新缓冲区。此时 recycled 的语义意义消失因为只有一个槽位不存在复用池的概念。标记recycled 0防止这个非标大小的缓冲区进入free链造成污染。2.3 末尾大数据或其他情况未进入上述两个子分支时last_in_chain为真但bsize 1.25 * size或num 1或directio为真保持size ctx-bufs.size和recycled 1recycled 1分配标准大小的缓冲区使用完毕后可回收到free链表供后续复用处理方式大数据量将被分多次拷贝到标准大小的缓冲区中ngx_buf_t.last_in_chain字段定义src/core/ngx_buf.hunsignedlast_in_chain:1;该位域位于ngx_buf_t结构体中与pos、last等指针字段同在一个结构体内。当上游模块确定当前缓冲区是响应体数据的最后一块时置 1。它独立于last_buf表示这是整个响应体的最后一块——last_in_chain是ngx_output_chain链内级别的信号而last_buf是 HTTP 层面的信号。3 分配缓冲区控制结构bngx_calloc_buf(ctx-pool);if(bNULL){returnNGX_ERROR;}处理逻辑分配并零初始化一个ngx_buf_t控制结构。ngx_calloc_buf宏定义src/core/ngx_buf.h#definengx_calloc_buf(pool)ngx_pcalloc(pool,sizeof(ngx_buf_t))展开为ngx_pcalloc(ctx-pool, sizeof(ngx_buf_t))——从 Nginx 内存池中分配一个ngx_buf_t大小的内存块并将所有位域清零。4 分配数据存储空间if(ctx-directio){/* * allocate block aligned to a disk sector size to enable * userland buffer direct usage conjunctly with directio */b-startngx_pmemalign(ctx-pool,size,(size_t)ctx-alignment);if(b-startNULL){returnNGX_ERROR;}}else{b-startngx_palloc(ctx-pool,size);if(b-startNULL){returnNGX_ERROR;}}ctx-directio是ngx_output_chain_ctx_s的位域字段由ngx_output_chain_align_file_buf在检测到 DirectIO 文件时置 1。4.1 DirectIO 路径b-startngx_pmemalign(ctx-pool,size,(size_t)ctx-alignment);进入条件ctx-directio 1。处理逻辑通过ngx_pmemalign分配一块按ctx-alignment磁盘扇区大小通常 512 字节对齐的内存。为什么 DirectIO 需要对齐DirectIOO_DIRECT绕过操作系统的页缓存直接从磁盘 DMA 传输数据到用户态缓冲区。这一机制要求用户态缓冲区地址按磁盘扇区边界对齐否则内核必须分配一块中间对齐缓冲区做中转拷贝——这恰恰是 DirectIO 想要避免的。ngx_pmemalign确保用户态缓冲区满足对齐要求使 DirectIO DMA 可以直接写入用户态缓冲区实现真正的零拷贝。4.2 普通路径b-startngx_palloc(ctx-pool,size);进入条件ctx-directio 0。处理逻辑通过ngx_palloc从 Nginx 内存池中分配size字节——不需要对齐约束。5 初始化缓冲区元数据b-posb-start;b-lastb-start;b-endb-lastsize;b-temporary1;b-tagctx-tag;b-recycledrecycled;字段初始化逐行解释字段赋值含义b-pos b-start读指针指向缓冲区起始位置初始时无可读数据pos与start同位置。数据被ngx_output_chain_copy_buf拷贝进来后dst-last后移此时last - pos即为已填充数据量b-last b-start写指针指向缓冲区起始位置初始时无已填充数据。ngx_output_chain_copy_buf填充数据后dst-last sizeb-end b-last size缓冲区尾部边界end - start size即分配的总容量。end - pos表示剩余可写入空间b-temporary 1标记为临时缓冲区告知下游该缓冲区数据可被修改区别于memory:1只读内存和mmap:1映射内存对应的内存将在请求结束时随内存池一起释放b-tag ctx-tag打上上下文标签tag用于ngx_chain_update_chains中的身份识别——只回收 tag 匹配的缓冲区避免跨请求/跨阶段的缓冲区误回收。ctx-tag由调用方在创建上下文时设置通常为模块指针b-recycled recycled回收标记recycled 1的缓冲区在发送完毕后会进入ctx-free链表供复用recycled 0的缓冲区在发送完毕后不会被回收到 free 链因为大小不标准不能复用6 注册到上下文ctx-bufb;ctx-allocated;returnNGX_OK;处理逻辑ctx-buf b将新分配的缓冲区注册到上下文中。ctx-buf是ngx_output_chain主循环中 拷贝步骤使用的工作缓冲区—ngx_output_chain_copy_buf从ctx-buf读取目标指针将源数据拷贝进去ctx-allocated递增已分配缓冲区计数。该计数在ctx-allocated ctx-bufs.num检查中用于限制同时存在的缓冲区数量达到上限后break退出内循环先发送已累积的数据释放空间返回NGX_OK告知上层调用者缓冲区已成功分配并初始化可以进入下一步ngx_output_chain_copy_buf进行数据拷贝。
延伸阅读

更多相关文章

2026/9/13 20:27:31

SoC超时垫片机制:从硬件原理到软件实战的可靠性设计

1. 系统互联中的“守门员”:超时与异常响应处理机制在复杂的SoC(片上系统)设计中,处理器核心、内存控制器、外设等数十甚至上百个IP模块通过高速片上互联网络(如VBUSM、AXI、CHI)进行通信。这个网络就像一座…

2026/9/15 0:51:00

Unity 塔防实战(十):一发子弹怎样完成命中与伤害结算

上一篇让 EDSkillBullet 经过延迟命令、类型注册和异步特效加载,变成了正在飞行的 SkillBullet。当追踪子弹到达目标、范围子弹找到怪物,或者碰撞子弹检测到敌人后,最终都会进入 SkillBullet.hit()。但“命中”并不只是血量减去攻击力:它还包含闪避、暴击、防御、元素抗性、…

2026/9/14 23:52:36

Unity 塔防实战(九):表格中的子弹怎样变成场景对象

上一篇分析到 TowerSkill 找到目标后,并不会立即在场景中生成子弹,而是按照 mFireTime 提交一个或多个 CmdCharacterFireBullet。延迟时间到达后,系统还要确认目标是否仍然有效、选择正确的子弹运行时类型、计算发射位置、加载飞行特效,并启动对应的轨迹。本文只回答一个核…

2026/9/15 0:51:19

Playwright拦截API实现高效数据采集实战

1. 项目背景与核心思路在当今数据驱动的互联网环境中,高效获取结构化数据已成为许多业务场景的刚需。传统爬虫技术通常采用"请求-解析HTML"的模式,但随着现代前端框架(如React/Vue)的普及和反爬机制的升级,这种模式面临三大痛点&am…

2026/9/15 0:51:19

YOLOv8分类模型OpenVINO CPU部署实战:ONNX转IR、INT8量化与C#调用

简介:本资源是一套基于C#与OpenVINO实现的YOLOv8图像分类(Cls)端到端部署方案,面向具备基础C#开发能力及计算机视觉入门经验的工程师与学习者,解决模型轻量化部署、CPU高效推理及Windows平台快速验证等实际问题。压缩包…

2026/9/15 0:51:19

WIZnet Port模块选型与应用指南

1. WIZnet Port模块概述WIZnet作为嵌入式网络通信领域的知名厂商,其Port模块系列产品在工业自动化、智能家居、物联网终端等领域有着广泛应用。这类模块本质上是一种硬件网络接口转换器,通过将微控制器的通用接口(如UART、SPI)转换…

2026/9/15 0:51:19

2025具身机器人芯片选型与优化实战指南

1. 2025具身机器人芯片格局解析当NVIDIA在2023年宣布Jetson AGX Thor芯片时,整个具身机器人行业为之一震。这颗基于Blackwell架构的SoC将机器人算力提升到了前所未有的2000TOPS,但真正改变游戏规则的是它对物理交互实时性的硬件级优化。我在机器人芯片选…

2026/9/15 0:46:19

猪行为识别数据集:从COCO标注到YOLOv8训练的完整实践

简介:一套面向智慧养殖场景的猪行为识别数据集,适合计算机视觉研发人员、农业工程研究者及畜牧智能化项目开发者使用。数据集聚焦猪圈内猪只的日常行为自动识别,覆盖喝、吃、睡觉、站立四个关键动作类别;标注文件采用COCO JSON格式…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/15 0:01:16

AI英语单词APP开发:自适应学习算法与移动端优化实践

1. 项目概述 作为一名在移动应用开发领域摸爬滚打多年的老手,我最近完成了一个AI英语单词APP的开发项目。这个项目将传统单词记忆方法与现代AI技术相结合,打造了一款能够智能适应不同用户学习习惯的英语学习工具。 市面上大多数单词APP都存在一个通病&a…

2026/9/15 0:01:16

Flutter与OpenHarmony结合开发手语学习APP实战

1. 项目背景与核心价值作为一名同时接触过Flutter和OpenHarmony的开发者,最近我完成了一个基于Flutter for OpenHarmony的手语学习APP实战项目。这个项目最大的特点在于实现了跨平台框架与国产操作系统深度结合的创新实践——用Flutter开发的应用能完美运行在OpenHa…

2026/9/15 0:01:16

六个月成为机器人工程师:从ROS2到SLAM的实战路径

1. 六个月的紧迫感从哪来:先搞清楚你要成为哪种机器人工程师说实话,六个月的期限并不是一个宽松的时间线。市面上任何一本正经的机器人学教材都超过五百页,ROS2的官方文档可以翻到你怀疑人生,再加上ABB、KUKA这些工业机器人厂家动…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码