`
xiqiao1229
  • 浏览: 13242 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Ningx代码研究(二)

阅读更多

内存分配相关

系统功能封装

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

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

  • ngx_alloc 使用malloc分配内存空间
  • ngx_calloc 使用malloc分配内存空间,并且将空间内容初始化为0
  • ngx_memalign 返回基于一个指定的alignment大小的数值为对齐基数的空间
  • ngx_free 对内存的释放操作

ngx的内存池

为了方便系统模块对内存的使用,方便内存的管理,nginx自己实现了进程池的机制来进行内存的分配和释放, 首先nginx会在特定的生命周期帮你统一建立内存池,当需要进行内存分配的时候统一通过内存池中的内存进行分配,最后nginx会在适当的时候释放内存池的资源,开发者只要在需要的时候对内存进行申请即可,不用过多考虑内存的释放等问题,大大提高了开发的效率。

内存池的主要结构为:

//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;
};

//ngx_core.h
typedef struct ngx_pool_s        ngx_pool_t;
typedef struct ngx_chain_s       ngx_chain_t;

下面是我简单画的一个图来描述这个结构:

link : http://www.flickr.com/photos/rainx/3765612584/sizes/o/

下面解释一下主要的几个操作:

// 创建内存池
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);

大致的过程是创建使用 ngx_alloc 分配一个size大小的空间, 然后将 ngx_pool_t* 指向这个空间, 并且初始化里面的成员, 其中

p->d.last = (u_char *) p + sizeof(ngx_pool_t); // 初始指向 ngx_pool_t 结构体后面
p->d.end = (u_char *) p + size; // 整个结构的结尾后面
p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; // 最大不超过 NGX_MAX_ALLOC_FROM_POOL,也就是getpagesize()-1 大小

其他大都设置为null或者0

// 销毁内存池
void ngx_destroy_pool(ngx_pool_t *pool);

遍历链表,所有释放内存,其中如果注册了clenup(也是一个链表结构), 会一次调用clenup 的 handler 进行清理。

// 重置内存池
void ngx_reset_pool(ngx_pool_t *pool);

释放所有large段内存, 并且将d->last指针重新指向 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_pcalloc(ngx_pool_t *pool, size_t size);
void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);

ngx_palloc的过程一般为,首先判断待分配的内存是否大于 pool->max的大小,如果大于则使用 ngx_palloc_large 在 large 链表里分配一段内存并返回, 如果小于测尝试从链表的 pool->current 开始遍历链表,尝试找出一个可以分配的内存,当链表里的任何一个节点都无法分配内存的时候,就调用 ngx_palloc_block 生成链表里一个新的节点, 并在新的节点里分配内存并返回, 同时, 还会将pool->current 指针指向新的位置(从链表里面pool->d.failed小于等于4的节点里找出) ,其他几个函数也基本上为 ngx_palloc 的变种,实现方式大同小异

// 释放指定的内存
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);

这个操作只有在内存在large链表里注册的内存在会被真正释放,如果分配的是普通的内存,则会在destory_pool的时候统一释放.

// 注册cleanup回叫函数(结构体)
ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);

这个过程和我们之前经常使用的有些区别, 他首先在传入的内存池中分配这个结构的空间(包括data段), 然后将为结构体分配的空间返回, 通过操作返回的ngx_pool_cleanup_t结构来添加回叫的实现。 (这个过程在nginx里面出现的比较多,也就是 xxxx_add 操作通常不是实际的添加操作,而是分配空间并返回一个指针,后续我们还要通过操作指针指向的空间来实现所谓的add)

下面是内存操作的一些例子 demo/basic_types/mem_op.c

#include <stdio.h>
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "nginx.h"
#include "ngx_core.h"
#include "ngx_string.h"
#include "ngx_palloc.h"

volatile ngx_cycle_t  *ngx_cycle;

void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
            const char *fmt, ...)
{
}

typedef struct example_s {
    int a;
    char* b;
} example_t;

int main()
{
    ngx_pool_t *pool;
    example_t* exp;
    char* s;

    pool = ngx_create_pool(5000, NULL);
    printf("available pool regular pool free size is %d now\n", (ngx_uint_t) (pool->d.end - pool->d.last));
    exp = ngx_palloc(pool, sizeof(example_t)) ;
    s = ngx_palloc(pool, sizeof("hello,world"));
    printf("available pool regular pool free size is %d now\n", (ngx_uint_t) (pool->d.end - pool->d.last));
    exp->a = 1;
    exp->b = s;
    strcpy(s, "hello,world");
    printf("pool max is %d\n", pool->max);
    printf("exp->a is %d, exp->b is %s\n", exp->a, exp->b);
    ngx_destroy_pool(pool);
    return 0;
}

编译运行结果

gcc  -c -O -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Wunused-function -Wunused-variable -Wunused-value -Werror -g -I ../../../objs/ -I ../../os/unix/ mem_op.c -I../../core/ -I../../event/ -I../../os/ -o mem_op.o
 gcc -o mem_op mem_op.o ../../../objs/src/core/ngx_{string,palloc}.o ../../../objs/src/os/unix/ngx_alloc.o -lcrypt -lpcre -lcrypto -lz
rainx@rainx-laptop:~/land/nginx-0.7.61/src/demo/basic_types$ ./mem_op 
available pool regular pool free size is 4960 now
available pool regular pool free size is 4940 now
pool max is 4960
exp->a is 1, exp->b is hello,world

分享到:
评论

相关推荐

    Nginx 代码研究

    #### 二、Nginx 代码研究目的 - **项目背景**:研究Nginx源代码的主要动机是为了完成分段反向代理项目的开发。分段反向代理需求较高,特别是对于Web服务器的并发性有较高要求。 - **研究动机**:当前关于Nginx的...

    NGINX 0.1版代码

    在0.1版代码中,可以研究NGINX如何解析配置文件,理解指令解析、变量处理等过程,这对于定制和扩展NGINX配置有很大帮助。 通过对NGINX 0.1版源代码的分析,我们可以深入了解其基本架构和设计原则。尽管随着版本...

    nginx Web服务器代码

    **Nginx Web服务器代码详解** Nginx是一款高性能、轻量级的Web服务器和反向代理服务器,因其高效的并发处理能力和低内存占用而受到广泛关注。它的设计目标是实现高并发、低延迟以及稳定性,因此在大型网站和互联网...

    nginx1.9.2源代码(内含大量注释的版本).zip

    在 `src/core/ngx_event.h` 和 `src/event/ngx_event.c` 中,可以研究 Nginx 如何高效地处理网络事件。 **3. 多进程与多线程** Nginx 通常采用主进程+工作进程的模式,主进程负责管理工作进程和配置加载,工作进程...

    nginx源代码1.13.10

    通过研究Nginx 1.13.10的源代码,开发者不仅可以了解其工作原理,还能深入学习网络编程、并发处理、I/O模型等相关知识,对提升系统级编程技能大有裨益。同时,这也是定制Nginx功能、优化服务器性能的重要途径。

    nginx开源代码

    本资源提供的"nginx开源代码"为nginx的1.3.1版本,虽然不是最新版,但对于学习其核心架构和基本工作原理非常有帮助。 Nginx的源码分析主要涉及以下几个关键知识点: 1. **事件模型**:Nginx采用的是异步非阻塞的...

    Nginx源代码分析最新版本

    Nginx源代码分析最新版本深入解析 Nginx,作为高性能的HTTP和反向代理服务器,以及IMAP/POP3/SMTP服务器,自推出...同时,我们也欢迎更多的朋友参与到Nginx源代码的研究和讨论中来,共同推动互联网技术的发展与进步。

    nginx源代码

    Nginx是一款高性能的HTTP和反向代理服务器,也是一款邮件代理服务器,广泛应用于互联网的高并发场景。其源代码的分析有助于...对于想要优化Nginx或者基于Nginx进行二次开发的工程师来说,理解源代码是至关重要的一步。

    nginx-0.0.1源代码

    - 源代码中关于静态文件的缓存和优化策略值得研究,以便提高服务效率。 7. **错误处理与日志记录** - Nginx 有完善的错误处理机制,包括记录错误日志、返回错误页面等,这些在实际运维中非常关键。 - 源代码中的...

    Nginx源代码分析.pdf

    深入研究Nginx的源代码,能帮助开发者理解如何构建高性能、低延迟的网络服务,并为自定义扩展提供基础。对于想要优化服务器性能或开发网络应用的人来说,理解Nginx的源代码无疑是一项重要的技能。

    NGINX源代码

    NGINX的源代码允许用户根据实际需求选择要编译进二进制文件的模块,以达到最小化安装的目标。这不仅减少了不必要的资源占用,也方便了对特定功能的支持。编译过程通常涉及`configure`脚本的运行,以及`make`和`make...

    nginx php mysql 源代码包

    3. **编译Nginx**:进入Nginx源代码目录,执行`./configure`进行配置,然后用`make`和`sudo make install`进行编译和安装。 4. **编译PHP**:在PHP源代码目录下,同样执行`./configure --with-nginx`指定Nginx路径...

    nginx-1.3.14 源代码

    深入研究 Nginx 1.3.14 的源代码,可以理解其模块化设计、事件驱动架构和高效并发处理能力。这对于开发基于 Nginx 的扩展功能或者优化现有部署都是必不可少的。同时,源代码中的注释也能帮助我们了解每个功能的实现...

    nginx web 服务器 代码

    通过学习和研究"nginx web服务器最新代码",我们可以深入理解Nginx的工作机制,同时也能为旧版本的维护和升级提供参考。无论是初学者还是经验丰富的开发者,对Nginx的深入理解都是提高服务质量的关键。

    nginx-0.1.0.hlf.tar.gz

    通过研究这个早期版本,你可以深入了解Nginx是如何从最初的代码逐渐演变为如今广泛使用的Web服务器的。同时,这个过程也是对Linux系统编程的一次深入实践,有助于提升你在C/C++编程、网络编程和系统调用方面的技能。

    nginx:Nginx的Git镜像源代码-git source code

    对于想要深入了解Nginx工作原理、进行定制化开发或者参与Nginx社区的开发者来说,研究其源代码是必不可少的步骤。你可以通过阅读源码了解Nginx如何处理网络请求、如何实现高效的并发处理机制,以及它是如何与其他...

    nginx源码学习资料

    然后,结合《深入理解Nginx》深入研究Nginx的内部机制。同时,通过阅读和分析Nginx源码,可以更直观地看到这些概念如何在实际代码中实现。 总之,掌握Nginx源码不仅可以提升Web服务的运维技能,还能为开发者提供一...

    nginx 源码 解析 资料大全

    收集的 nginx 源码 解析 ,非常全 architecture.png Emiller的Nginx模块开发指南.docx Nginx(en).pdf nginx@taobao.pdf nginx_internals.pdf nginx核心讲解(0.2).doc nginx核心讲解(0.4).doc ...Ningx代码研究.docx

    nginx:nginx源代码+学习笔记

    **Nginx源代码分析与学习笔记** Nginx是一款高性能、轻量级的Web服务器/反向代理服务器,以其高效的并发处理能力、低内存占用和丰富的模块化设计而受到广泛应用。本文将深入探讨Nginx的源代码,并结合学习笔记,...

    nginx源码1.5.7版本

    通过研究Nginx 1.5.7的源码,我们可以深入了解网络服务器的设计理念,学习如何构建高性能、高并发的应用。同时,对于希望改进或定制Nginx功能的开发者来说,源码阅读是必不可少的步骤。通过深入源码,我们可以发现更...

Global site tag (gtag.js) - Google Analytics