nginx 源码学习笔记(七)——内存分配相关源码分析

内存分配相关

1.系统功能封装

内存相关的操作主要在os/unix/ngx_alloc.{h,c} 和 core/ngx_palloc.{h,c}中。

其中os/unix/ngx_alloc.{h,c}封装了最基本的内存分配函数,是对c原有的malloc/free/memalign等函数的封装,对应函数为:

a.ngx_alloc:对malloc进行了简单的封装;

void * ngx_alloc(size_t size, ngx_log_t *log) { void *p; p = malloc(size); if (p == NULL) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "malloc(%uz) failed", size); } ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size); return p; }

b.ngx_calloc:使用ngx_alloc分配内存,并且把内存赋值0:

void * ngx_calloc(size_t size, ngx_log_t *log) { void *p; p = ngx_alloc(size, log); if (p) { ngx_memzero(p, size); }在core/ngx_string.h中定义 // #define ngx_memzero(buf, n) (void) memset(buf, 0, n) 初始化为0 return p; }

c. ngx_memalign 返回基于一个指定的alignment大小的数值为对齐基数的空间

d.ngx_free 内存释放操作

2. nginx内存池

为了方便系统模块对内存的使用,方便内存的管理,nginx自己是信了进程池机制来进行内存的分配和释放,首先nginx会在特定的生命周期帮你统一建立内存池,当需要进行内存分配的时候同一通过内存池中的内存进行分配,最后nginx会在适当的时候释放内存吃的资源,开发者只要在需要的时候对内存进行申请即可,不用过多考虑释放的问题,这也就是在os/unix/ngx_alloc.c文件中没有看到free操作的原因吧。

下面来看一下内存池的主要结构:

ngx_palloc.h struct ngx_pool_s { ngx_pool_data_t d; size_t max; ngx_pool_t *current; ngx_chain_t *chain; ngx_pool_large_t *large; ngx_pool_cleanup_t *cleanup; ngx_log_t *log; }; typedef struct { u_char *last; u_char *end; ngx_pool_t *next; ngx_uint_t failed; } ngx_pool_data_t; ngx_core.h typedef struct ngx_pool_s ngx_pool_t; typedef struct ngx_chain_s ngx_chain_t;

下面是几个比较重要的操作


src/core/ngx_palloc.c //创建内存池 ngx_pool_t * ngx_create_pool(size_t size, ngx_log_t *log) { ngx_pool_t *p; p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); //创建对其空间 if (p == NULL) { return NULL; } p->d.last = (u_char *) p + sizeof(ngx_pool_t); //初始指向ngx_pool_t结构体后面 p->d.end = (u_char *) p + size; //整个结构体的结尾 p->d.next = NULL; //没有next p->d.failed = 0; size = size - sizeof(ngx_pool_t); //剩余大小 p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL;//最大不超过NGX_MAX_ALLOC_FROM_POOL //#define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1) p->current = p; p->chain = NULL; p->large = NULL; p->cleanup = NULL; p->log = log; return p; } //销毁内存池 void ngx_destroy_pool(ngx_pool_t *pool) { ngx_pool_t *p, *n; ngx_pool_large_t *l; ngx_pool_cleanup_t *c; for (c = pool->cleanup; c; c = c->next) {//如果注册了clenup(一种链表结构),会依次调用clenup的handler进行清理 if (c->handler) { ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "run cleanup: %p", c); c->handler(c->data); } } for (l = pool->large; l; l = l->next) { //遍历链表,释放所有large内存 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc); if (l->alloc) { ngx_free(l->alloc); } } #if (NGX_DEBUG) //等译debug级别,如果为true,会打印日志 /* * we could allocate the pool->log from this pool * so we cannot use this log while free()ing the pool */ for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p, unused: %uz", p, p->d.end - p->d.last); if (n == NULL) { break; } } #endif for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {//遍历链表 ,释放内存空间 ngx_free(p); if (n == NULL) { break; } } } //重置内存池 void ngx_reset_pool(ngx_pool_t *pool) { ngx_pool_t *p; ngx_pool_large_t *l; for (l = pool->large; l; l = l->next) { //释放掉所有large段内存 if (l->alloc) { ngx_free(l->alloc); } } pool->large = NULL; for (p = pool; p; p = p->d.next) { p->d.last = (u_char *) p + sizeof(ngx_pool_t);将指针重新指向ngx_pool_t(和创建时一样) } } //从内存池里分配内存 void * ngx_palloc(ngx_pool_t *pool, size_t size) void * ngx_pnalloc(ngx_pool_t *pool, size_t size) void * ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment) void * ngx_pcalloc(ngx_pool_t *pool, size_t size) 这里以ngx_palloc为例讲解,其他大同小异: void * ngx_palloc(ngx_pool_t *pool, size_t size) { u_char *m; ngx_pool_t *p; if (size <= pool->max) { //判断分配内存是否大于pool->max,如果小于等于 p = pool->current; //尝试从链表的current开始遍历, do { m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); //#define ngx_align_ptr(p,a) //(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) if ((size_t) (p->d.end - m) >= size) { //当找到可以分配的空间时 p->d.last = m + size; return m; //分配内存后返回 } p = p->d.next; } while (p); return ngx_palloc_block(pool, size);//如果无法分配内存,就生成一个新的节点,同时pool->current指针指向新的位置 } return ngx_palloc_large(pool, size); //如果分配的内存大于pool->max则在large链表分配一段内存 } //释放指定的内存 ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p){ ngx_pool_large_t *l; for (l = pool->large; l; l = l->next) { if (p == l->alloc) { //存在alloc注册 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "free: %p", l->alloc); ngx_free(l->alloc); l->alloc = NULL; return NGX_OK; } } return NGX_DECLINED; }//由代码可以看出,这个操作只有在内存large链表里面注册内存才会真正释放,如果分配的是普通的内存,则会在destory_pool的时候统一释放。 //注册cleanup回调函数 ngx_pool_cleanup_t * ngx_pool_cleanup_add(ngx_pool_t *p, size_t size) { ngx_pool_cleanup_t *c; c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t)); //分配cleanup空间 if (c == NULL) { return NULL; } if (size) { c->data = ngx_palloc(p, size); //为cleanup结构体分配data空间 if (c->data == NULL) { return NULL; } } else { c->data = NULL; } c->handler = NULL; c->next = p->cleanup; p->cleanup = c; // 增加cleanup ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c); return c; //返回结构体分配的空间 }

易语言申请内存源码-易语言 易语言申请内存源码 立即下载

相关推荐

易语言申请进程堆栈内存

易语言申请进程堆栈内存源码,申请进程堆栈内存,申请堆栈内存,取CPU型号_汇编版,释放堆栈内存,从堆栈分配内存_,释放堆栈内存_,取进程堆栈句柄_

Nginx 核心架构与开发指南

本文将详细介绍 Nginx 的代码布局、基础类型、模块架构、事件驱动模型、HTTP 核心实现、内存管理、共享内存与多进程模型、异步I/O与线程池、模块开发规范等内容,并附上示例代码与最佳实践,以期帮助开发者快速上手 Nginx 二次开发与模块编写。

hello.reader 1255

PLC模拟量输入电路设计:±10V与±20mA信号调理全解析

在工业自动化和数据采集系统中,模拟量输入是连接物理世界与数字控制的核心桥梁。无论是变送器输出的4-20mA电流环,还是伺服驱动与信号发生器提供的±10V电压信号,PLC和采集模块都需要在复杂现场环境下稳定、精准地完成信号采集。理解信号体制的原理——电流环抗长线干扰、电压环响应快——是设计模拟输入前端的基础。通过精密电阻网络实现分压与采样,利用运放完成双极性到单极性的电平搬移,配合TVS与滤波电路保障可靠性,并经过ADC量化与校准流程,最终构建出兼顾精度、成本和工业级鲁棒性的完整信号链路。本文面向硬件工程师与

weixin_29163797的博客 300

Nginx源码分析--内存池

NGINX通过ngx_create_pool创建内存池。参数size用来指定从内存池的小块内存区域总共可以获取的内存的最大,同时也是可以申请的单个小块内存的最大size。在函数执行过程中size会转化成16的整数倍。

qq_62309585的博客 1624

CV领域交叉注意力机制:QKV在图像特征增强中的核心作用解析

本文深入解析了CV领域中交叉注意力机制的核心组件QKV在图像特征增强中的关键作用。通过通俗类比和实战案例,阐述了Q(查询)、K(键)、V(值)如何协同实现动态权重分配,从而在目标检测、图像分割与生成等任务中显著提升模型性能与语义对齐能力。

weixin_29194817的博客 438

无刷电机控制避坑指南:六步换向 vs FOC的5个关键差异

本文深入对比了无刷电机控制中六步换向与FOC(磁场定向控制)的五大核心差异。从控制逻辑、性能表现、效率能耗、硬件成本到应用场景,详细解析了FOC如何通过矢量合成实现平滑的正弦波控制与更高效率,而六步换向则以低成本实现简单开关驱动。旨在帮助工程师根据项目需求,在性能、成本与复杂度间做出最佳选择。

weixin_29216957的博客 507

Nginx内存管理详解

Nginx内存管理详解 目录: 1.Nginx内存管理介绍 2.Nginx内存池的逻辑结构 3.Nginx内存池的基本数据结构 4.内存池基本操作介绍 5.内存池管理源码详解 6.内存池使用源码详解 7.小结 1.Nginx内存管理介绍   在C/C++语言程序设计中,通常由程序员自己管理内存的分配和释放,其方式通常是malloc(free)和new(dele...

weixin_30491641的博客 584

STM32CubeMX定时器配置

因为只有当 CH2 处于 输入模式 时,硬件才能把这根脚送进滤波器(TI2FP2通道之前要滤波),再生成 TI2FP2 这条支路供 Slave-Mode 控制器使用,也就是说TI2FP2 并不是“独立存在”的,但在CubeMX配置时:如下图,我们只设置Slave Mode和TI1FP1,之后,CH1就自动配置为 Input Capture 了,下图发现,Channel1只能 Input Capture 或者Disable。哪来的主定时器和从定时器呢?把待测 PWM 的高电平当“门”,连接到ETR。

2402_89015641的博客 3185

nginx源码学习----内存池

最近在进行监控平台的设计,之前一直觉得C/C++中最棘手的部分是内存的管理上,远不止new/delete、malloc/free这么简单。随着代码量的递增,程序结构复杂度的提高。各种内存方面的问题悄然滋生。而且作为平台,后期的插件扩展在所难免。长时间运行的采集平台的特性更是提出了对稳定性的高要求。不是c#、java,没有虚拟机为你管理内存,一切都要靠自己。于是想看看nginx、python、lua...

weixin_30894389的博客 223

virtuoso根据原理图绘制版图并联接_virtuoso画原理图

Virtuoso Schematic Editor 电路仿真一、Virtuoso Schematic Editor 实验目的:掌握电原理图(schematic)设计输入方法。 [1]启动 IC Design 软件 启动 软件: 开机后运行......2.绘制原理图 新建工程后打开的是默认的原理图文件 SCHEMATIC1 PAG...存盘 完成原理图的绘制后,将原理图存盘. 三 . 用 Check...

weixin_33536190的博客 4144

【原理图与PCB专题】使用Cadence如何在Layout时直接互换相同功能的PIN

Cadence允许我们在PCB中互换管脚,最后再反标给原理图。集成TVS管、排阻、DDR、FPGA有一些PIN是完全相同功能,可进行管脚互换的,建议使用这个功能。可降低硬件工程师与Layout工程师之间沟通成本,加快设计进度。

一点硬件 801

Nginx内存池源码分析

Nginx内存池 Nginx简介 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。 其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和...

javanmsl的博客 538

2025 华为OD机试真题e卷 C语言 实现【竖直四子棋】

竖直四子棋的棋盘是竖立起来的,双方轮流选择棋盘的一列下子,棋子因重力落到棋盘底部或者其他棋子之上,当一列的棋子放满时,无法再在这列上下子。

MISAYAONE的博客 1417

nginx源码分析和openresty源码分析

nginx nginx可以作为网关(负载均衡,路由规则,限流,访问控制),缓存服务器,web服务器(可以使用lua开发,openresty框架),反向代理服务器。 支持http,https,http/2,grpc,tcp,udp,websocket协议。 源码结构 src/core (底层核心结构) 启动入口和基础的数据结构和算法。 nginx.c就是入口,初始化,启动多进程。 数据结构 ngx_array ngx_buf ngx_conf_flie ngx_connection ngx_core ngx_

u013860464的博客 4410

超详细教程YoloV8官方推荐免费数据集网站Roboflow一键导出Voc、COCO、Yolo、Csv等格式

YoloV8官方推荐了一个数据集网站,就是Roboflow。Roboflow是一个数据集管理平台,提供了免费的数据集,同时也支持上传自己的数据集进行格式转换。使用Roboflow,开发者可以方便地获取所需格式的数据集,无需手动转换格式。此外,Roboflow还提供了多种数据预处理、数据增强等功能,可帮助开发者更好地优化训练数据

Snu77的博客 2万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_pnalloc函数

这种设计的目标是减少内存碎片、提高分配效率,并通过集中管理内存生命周期来简化内存释放操作。如果当前内存池的空闲空间不足,则会创建一个新的内存块并挂载到内存池中。分配的内存会被记录在内存池的大块内存链表中,以便在内存池销毁时统一释放。根据分配的大小,它会选择不同的分配策略(小块或大块)是一个小块内存分配器,它会尝试从内存池的空闲链表中分配内存。声明在 src\core\ngx_palloc.h。是内存池的一个属性,表示小块内存分配的最大限制。该函数的作用是从指定的内存池中分配一块大小为。

weixin_41812346的博客 546

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_create_pool函数

定义一个指针变量p,用于存储新创建的内存池对象的地址。

weixin_41812346的博客 706

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

nginx源码学习笔记

nginx 源码学习笔记(一)——初识nginx helloworld模块 nginx 源码学习笔记(二)——nginx精粹-模块 nginx 源码学习笔记(三)——nginx精粹-模块 nginx 源码学习笔记(四)——nginx精粹-模块 nginx 源码学习笔记(五)——nginx精粹-模块 nginx 源码学习笔记(六)——nginx基本数据结构 nginx 源码学习笔记(七)——内存分配相关源码分析 nginx 源码学习笔记(八)——基本容器——array数组 nginx 源码学习笔记(九)——基

qq_23350817的博客 271
上一篇: nginx 源码学习笔记(七)——内存分配相关源码分析
下一篇: Android 4.0中按键的处理流程
piperzero
博客等级 码龄21年 1377粉丝 504原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值