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进行数据拷贝。

相关新闻

互联网大厂常见Java面试题及答案汇总(2026持续更新)

互联网大厂常见Java面试题及答案汇总(2026持续更新)

金九银十即将来袭,又是一个跳槽的好季节,准备跳槽的同学都摩拳擦掌准备大面好几场,今天为大家准备了互联网面试必备的 1 到 5 年 Java 面试者都需要掌握的面试题,分别 JVM,并发编程,MySQL,Tomca…

2026/7/20 0:15:05阅读更多 →
python数据可视化技巧的100个练习 -- 31. 类别数据的点图

python数据可视化技巧的100个练习 -- 31. 类别数据的点图

重要性★★★☆☆ 难度★★☆☆☆ 你是一家零售公司的数据分析师。你的经理要求你可视化最近产品发布的客户满意度评级分布。评级是分类的,范围从“非常不满意”到“非常满意”。创建一个点图以显示每个评级类别的频率。使用 Python 进行数据处理和可视化。在代码中生成输入…

2026/7/20 0:13:05阅读更多 →
智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

在2026世界人工智能大会(WAIC 2026)举办期间,千里科技董事长、阶跃星辰董事长印奇作为特邀嘉宾出席大会开幕式并在大会主论坛(上午场)发表主题演讲《当智能体进入物理世界》。在印奇看来,"智能体"…

2026/7/20 0:13:05阅读更多 →
HarmonyOS应用开发实战:小事记 - oh-package.json5 依赖管理:@ohos 与 @kit 的模块化演进

HarmonyOS应用开发实战:小事记 - oh-package.json5 依赖管理:@ohos 与 @kit 的模块化演进

前言 HarmonyOS 的依赖管理系统经历了从 ohos 原生模块到 kit Kit 化模块的重大演进。oh-package.json5 作为项目的依赖声明文件,管理着从测试框架到业务库的所有三方依赖。理解 ohos 与 kit 的模块化设计理念、依赖版本管理策略和多模块工程的依赖配置&#xff0c…

2026/7/20 16:34:16阅读更多 →
HarmonyOS应用开发实战:小事记 - 应用包结构:HAP/HSP/HAR 的三层架构与 deliveryWithInstall 策略

HarmonyOS应用开发实战:小事记 - 应用包结构:HAP/HSP/HAR 的三层架构与 deliveryWithInstall 策略

前言 HarmonyOS 的应用包结构采用了分层模块化设计,将代码和资源组织为 HAP(HarmonyOS Ability Package)、HSP(HarmonyOS Shared Package)和 HAR(HarmonyOS Archive)三种包格式。这种设计使得应…

2026/7/20 16:34:16阅读更多 →
HarmonyOS应用开发实战:小事记 - Stage 模型下 EntryAbility 的启动流程与 Want 解析机制

HarmonyOS应用开发实战:小事记 - Stage 模型下 EntryAbility 的启动流程与 Want 解析机制

前言 HarmonyOS 从 API 9 开始全面推行 Stage 模型,替代了早期版本的 FA(Feature Ability)模型。Stage 模型的核心设计理念是将组件生命周期、窗口管理和任务调度三者解耦,为应用提供更精细化的控制能力。本文基于 小事记&#x…

2026/7/20 16:34:16阅读更多 →
小米(南京)业务中台技术专家 / AI Agent 中台技术主管

小米(南京)业务中台技术专家 / AI Agent 中台技术主管

小米「AI Agent 中台技术主管」岗位 面试全案 岗位:小米(南京)业务中台技术专家 / AI Agent 中台技术主管 候选人:10 年大厂经验,阿里 5 年 + 字节 5 年,AI Agent 架构师 / 后端 & 大数据专家 编制日期:2026-07-18 文档结构:开场自我介绍 → 跳槽原因深度思考 → …

2026/7/20 16:34:16阅读更多 →
璞睿(PRIMEAI)数智化全生命周期解决方案完整深度解读

璞睿(PRIMEAI)数智化全生命周期解决方案完整深度解读

文章目录璞睿数智化全生命周期解决方案完整深度解读整体框架总览一、中心核心:PRIME CORE 璞睿核心技术中台(全体系底层基座)1. 工具:EMR-to-EDC2. 知识:知识图谱 NLP AI算法3. 数据:中心数据云平台&…

2026/7/20 16:34:16阅读更多 →
ELK.js:如何用JavaScript解决复杂图表自动布局的三大难题?

ELK.js:如何用JavaScript解决复杂图表自动布局的三大难题?

ELK.js:如何用JavaScript解决复杂图表自动布局的三大难题? 【免费下载链接】elkjs ELKs layout algorithms for JavaScript 项目地址: https://gitcode.com/gh_mirrors/el/elkjs 在数据可视化和图表编辑领域,开发者在处理复杂流程图、…

2026/7/20 16:32:15阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 0:50:54阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 0:50:54阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 0:50:54阅读更多 →
2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息,在2026 WAIC期间,努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相,相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示,智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:01:04阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra:外观与功能双升级在2026 WAIC期间,首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”,与一代努比亚M153相比,外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:01:04阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1:使用Split和Convert.ToInt64 方法2:使用LINQ的Select和ToList 方法3:使用TryParse进行异常安全转换(推荐) 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天…

2026/7/20 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/19 22:50:49阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/19 14:50:26阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/19 18:50:36阅读更多 →