`
xiqiao1229
  • 浏览: 12786 次
  • 性别: 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的例子很少,主要是emiller的模块开发介绍这篇文章, 但是单独研究这篇文章发现很多晦涩难懂的地方,而目前还没有其他更好的文章来对这些地方做解释, 有些东西必须要通过源代码的研读才可以...

    NGINX 0.1版代码

    这是NGINX的0.1版源代码,模块结构相对简单,适用于有志研究NGINX代码的童鞋进行学习。

    nginx 各个历史版本

    nginx各个阶段的历史版本源码,从0.1版本开始,可以用于研究nginx的代码框架

    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的源码进行学习研究是早在2009年的事情,当时还在学校,整天呆在实验室里看动漫,时间一久就心感愧疚,觉得还是要趁有空学点东西,恰当时不知从哪里得知高性能服务器是一个很有“前途”的方向,几经搜索...

    Nginx经典模块

    为什么发现了这个插件,因为这几天公司需要在所有shtml文件后面追加一个js代码用来做统计(之前统计 代码没加齐全),在寻求解决方法的过程中找到了它认识了它最后喜欢上了它,你可能以为我用这个插件去实现了我要的...

    Nginx源码研究之nginx限流模块详解

    主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    nginx源码vs2008版

    nginx最近是越来越火,许多大型商业网站都用它作服务器,作为开发人员很有必要拿来研究一下。从网上下来的都是make版,代码看起来不是那么方便,特别是对我这种习惯vs的程序员,幸好有朋友整理了一下,在vs2008下,...

    Nginx配置实现下载文件的示例代码

    所以今天就想研究下nginx实现文件的上传下载,直接开搞,本地服务启起。这里记录下配置及踩坑记录。 一、配置 http { ... server: { # 配置下载 location /download { root D:\\download; autoindex on; ...

    详解Nginx服务器的nginx-http-footer-filter模块配置

    为什么发现了这个插件,因为这几天公司需要在所有shtml文件后面追加一个js代码用来做统计(之前统计代码没加齐全),在寻求解决方法的过程中找到了它认识了它最后喜欢上了它,你可能以为我用这个插件去实现了我要的...

    Linux上搭建nginx,及简单配置

    在上家公司都是运维安装nginx,到新公司后代码开发完成部署测试服务器要求自己装nginx,研究了好久安装好之后,到正式上线还要自己安装,索性把安装步骤自己记载下来(好大一部分都是在网站找的)。  一,安装  ...

    解析CI即CodeIgniter框架在Nginx下的重写规则

    最近研究CI框架,发现这个框架的路由功能在Nginx下有问题,报404错误,后来在网上查资料,发现需要开启PATH_INFO。在nginx7.16以后貌似就支持PATH_INFO了,只需要在配置文件中开启即可。打开nginx.conf文件,在你的...

    交易所源码分享,原生安卓+ios,有安装教程!

    项目所需软件 (推荐使用宝塔安装) Nginx、php、mysql、redis、supervisor 进行部署项目 以下安装步骤仅以宝塔环境...仅限用于学习和研究目的,不得将上述内容资源用于商业或者非法用途,否则,一切后果请用户自负。

    nginx try_files指令判断文件是否存在实例

    现在有这样一个需求,网站根目录下有静态文件,static目录下也有静态文件,static目录下的静态文件是程序批量生成的,我想让nginx在地址不变的前提下优先使用static目录里面的文件,如果不存在再使用根目录下的静态...

    Answer-Prediction:代码研究员小组项目

    一个代码研究员小组项目,由四个学生在一周内完成。 Sherlock Engine是一个基于Python的应用程序,它使用多元线性回归来预测用户对下一个问题的答案。 每次用户提交答案时,对于该用户以及所有其他用户,所有后续...

    openresty_dev:OpenResty开发指南代码

    openresty_dev 这是OpenResty编程的示例代码。...注释nginx,学习研究原始码 选定的收藏夹nginx模块和资源。 带有google_perftools的nginx更好的工具 -Boost库指南的示例代码。 专业促进发展。

    毕业设计-浅谈nginxlua在安全中的应用.zip

    这里为你收集整理了关于毕业设计、课程设计可参考借鉴的资料一份,质量非常高,如果你投入时间去研究几天相信肯定对你有很大的帮助。到时候你会回来感谢我的。 本资源是经过本地编译测试、可打开、可运行的项目、...

    PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径

    我在服务器上有每天切割nginx日志的习惯,所以针对每天各大搜索引擎来访,总能记录一些404页面信息,传统上我只是偶尔分析下日志,但是对于很多日志信息的朋友,人工来筛选可能不是一件容易的事情,这不我个人自己...

    外贸网站屏蔽中国IP访问的多种方法

    大家都知道的原因,做外贸站,国人喜欢研究你的站,还总是帮你进行压力测试…… 首先想到要屏蔽中国IP就会是把中国IP库加入Nginx配置文件中,然后WEB服务器对比IP来达到屏蔽。 代码如下: 在Nginx中加deny IP; 批量...

Global site tag (gtag.js) - Google Analytics