Nginx

Nginx的特点就是占用内存少,并发能力强.


Nginx的内存管理采用内存池管理,当从内存池存取数据时,Nginx的的是分为两种类型来处理的,一种是小块数据,是直接从内存池中存取数据; 另一方面,当为大块数据时,它是直接malloc的一块数据(也就是从内存池外分配数据),然后保存这个这个指针到内存池。


其实,Nginx的和STL中空间配置器的内存管理方式类似,接下来进行对的的Nginx的的内存管理的分析(基于Nginx1.3.1版本源代码)。

-------------------------------------------------- --------------------------


1. Nginx的内存分配的主要过程(如下图),

2. Nginx内存池的相关数据结构关系


3. Nginx内存池的基本结构之间的关系


4.内存池提供的接口

void * ngx_alloc(size_t size,ngx_log_t * log);
void * ngx_calloc(size_t size,ngx_log_t * log);

ngx_pool_t * ngx_create_pool(size_t size,ngx_log_t * log);
void ngx_destroy_pool(ngx_pool_t * pool);
void ngx_reset_pool(ngx_pool_t * pool);
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_int_t ngx_pfree(ngx_pool_t * pool,void * p);

ngx_pool_cleanup_t * ngx_pool_cleanup_add(ngx_pool_t * p,size_t size);
void ngx_pool_run_cleanup_file(ngx_pool_t * p,ngx_fd_t fd);
void ngx_pool_cleanup_file(void * data);
void ngx_pool_delete_file(void * data);


5.内存池操作

5.1创建内存池


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);
    p-> d.end =(u_char *)p + size;
    p-> d.next = NULL;
    p-> d.failed = 0;

    size = size  -  sizeof(ngx_pool_t);
    p-> max =(size <NGX_MAX_ALLOC_FROM_POOL)?size:NGX_MAX_ALLOC_FROM_POOL;

    p-> current = p;
    p-> chain = NULL;
    p-> large = NULL;
    p-> cleanup = NULL;
    p-> log = log;

     return p;
}

创建内存池ngx_create_pool中调用内存分配函数ngix_memalign,具体如下:

#define NGX_POLL_ALIGNMENT 16
// nginx的以16字节对齐
void * ngx_memalign(size_t alignment,size_t size,ngx_log_t * log){
     void * p;
     int err;
     err = posix_memalign(&p,alignment,size);
     if(err){
         ngx_log_err(NGX_LOG_EMERG,log,err,“posix_memalign(&uz,&uz)failed”),对齐方式,这些
     对象的大小字节的内存大小,尺寸);
         p = NULL;
      }
      return p;
}

函数分配以NGX_POOL_ALIGNMENT字节对齐的大小字节的内存,就是以16字节对齐的

#define NGX_POOL_ALIGNMENT 16 


5.2重置内存池


ngx_reset_pool函数主要分为两步:


(1)释放的大内存块


(2)重置小内存块,将d.next指针重新指向ngx_pool_t结构之后数据区的开始位置,使内存池恢复到刚创建时的位置。


由于内存池刚被创建初始化时是不包含大块内存的,所以必须要释放大块内存。


在内存池摧毁ngx_destroy_pool中,小块数据是从来不释放的。

void
ngx_reset_pool(ngx_pool_t * pool){
    ngx_pool_t * p;
    ngx_pool_large_t * l;

    for(l = pool-> large; 1; l = 1->next){
        if(l->alloc){
            ngx_free(1-> ALLOC);
        }
    }
    pool-> large = NULL;

    for(p = pool; p; p = p->d.next){
        p-> d.last =(u_char *)p + sizeof(ngx_pool_t);
    }
}
5.3内存池的销毁


 内存池的销毁主要分为三步:


(1)清理工作


        先清理cleanup链表上的数据;


        然后调用handler释放清理数据。


(2)清理大块内存,调用ngx_free()释放内存


(3)遍历小块内存池,然后再一次释放内存池链表

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){
        if(c-> handler){
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC,pool-> log,0,
                           “运行清理:%p”,c);
            c->handler(c->data);    //调用ngx_pool_clean_t的清理函数处理程序
        }
    }

	/// free大块内存
    for(l = pool->large; l; l=l->next){
        ngx_log_debug1(NGX_LOG_DEBUG_ALLOC,pool-> log,0,“free:%p”,l-> alloc);

        if(l-> alloc){
            ngx_free(1-> ALLOC);
         #if(NGX_DEBUG)
         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 。持续);
        if(n == NULL){
            break;
        }
    }
#endif
	//遍历小块内存池
	//小块数据是从来不释放的
    for(p = pool,n = pool->d.next; / * void * /; p = n,n = n  - > d.next){
        ngx_free(P);    //直接free掉
        if(n == NULL){
            break;
        }
    }		
}


文章来源: Nginx

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:Nginx