nginx内存池原理

1 nginx内存池介绍

内存池实现原理主要分为分配,回收,扩容三部分。nginx内存池实现也是这样的。
对于nginx而言,内存池是分等级的,启动时每创建一个worker进程就会分配一个进程级内存池,当客户端有一个连接(http,tcp,udp等)连上后就会在当前的进程级内存池在分配创建一个连接级内存池,在这个连接中客户端request一个请求时,会在连接级内存池中分配创建一个请求内存池;服务器与这个连接的所有操作都是在对应的内存池中处理,如果客户端断开连接后,服务器就会释放对应的内存池.
大体逻辑
Nginx的内存池的使用主要是在各个连接到达之后为每个连接单独开辟一个内存池,在连接关闭后释放这个内存池
1 请求 nginx中一个http,tcp,udp请求再服务器这边就会创建一个对应的内存池,对这个请求操作,就找对应的这个内存池操作就好
2 分配nginx分配内存区分大块内存,小块内存;当小于pool->max时候就是再内存池中分配内存,如果内存池空间不够,则需要开新的快来处理;
申请的空间大于pool->max时候,就直接malloc开辟然后挂载到pool->large链表下面
3 释放 在释放内存时,nginx 没有专门提供针对释放小块内存的函数,小块内存会在 ngx_destory_pool 和 ngx_reset_pool 的时候一并释放。
内存分配逻辑
分配一块内存,如果分配的内存 size 小于内存池的 pool->max 的限制,则属于小内存块分配,走小内存块分配逻辑;否则走大内存分配逻辑。小内存分配逻辑:循环读取 pool->d 上的内存块,是否有足够的空间容纳需要分配的 size,如果可以容纳,则直接分配内存;否则内存池需要申请新的内存块,调用 ngx_palloc_block。
大内存分配逻辑:
当分配的内存 size 大于内存池的 pool->max 的限制,则会直接调用 ngx_palloc_large 方法申请一块独立的内存块,并且将内存块挂载到 pool->large 的链表上进行统一管理。

2 数据结构

区分大块,小块,cleanup机制

// cleanup结构
typedef void (*ngx_pool_cleanup_pt)(void *data);
typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;
struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;  // 自定义回调函数
    void                 *data;     // 内存对应的数据回调函数参数
    ngx_pool_cleanup_t   *next;     //  链表
};

// cleanup file
typedef struct {
    ngx_fd_t              fd;
    u_char               *name;
    ngx_log_t            *log;
} ngx_pool_cleanup_file_t;


// 大块空间  链表
typedef struct ngx_pool_large_s  ngx_pool_large_t;
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;		// 链表
    void                 *alloc;	// 内存空间
};

// 小块空间  链表
typedef struct {
    u_char               *last;   // 当前的开始分配的位置
    u_char               *end;	  // 当前块的结束位置
    ngx_pool_t           *next;   // 链表
    ngx_uint_t            failed; // 当前块最后一点空间,分配次数还是未成功就抛弃
} ngx_pool_data_t;


// 管理组件(内存池)
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;  // cleanup机制
    ngx_log_t            *log;      // 日志
};

3 对应api

创建内存池
nginx内存池原理_第1张图片
分配内存
在小块中分配内存结点
nginx内存池原理_第2张图片
如果当前小块的内存不足够分配,开辟新的小块
nginx内存池原理_第3张图片
开辟大块空间
nginx内存池原理_第4张图片
消耗内存池
nginx内存池原理_第5张图片
cleanup机制
可以回调函数清理数据 与内存池无关,只是内存池再释放的时候帮你回收一些资源
Nginx 的内存池 cleanup 机制,设计的非常巧妙。pool->cleanup 本身是一个链表,每个 ngx_pool_cleanup_t的数据结构上,保存着内存数据的本身 cleanup->data 和回调清理函数 cleanup->handler。通过 cleanup 的机制,我们就可以在内存池上保存例如文件句柄 fd 的资源。当我们调用 ngx_destroy_pool 方法销毁内存池的时候,首先会来清理 pool->cleanup,并且都会执行 c->handler(c->data)回调函数,用于清理资源。Nginx 的
这个机制,最显著的就是让文件描述符和需要自定义清理的数据的管理变得更加简单。分配一个 cleanup 结构:

分配一个可以用于回调函数清理内存块的内存
内存块仍旧在 p->d 或 p->large 上
ngx_pool_t 中的 cleanup 字段管理着一个特殊的链表,该链表的每一项都记录着一个特殊的需要释放的资源。
对于这个链表中每个节点所包含的资源如何去释放,是自说明的。这也就提供了非常大的灵活性。
意味着,ngx_pool_t 不仅仅可以管理内存,通过这个机制,也可以管理任何需要释放的资源,
例如,关闭文件,或者删除文件等等的。下面我们看一下这个链表每个节点的类型
一般分两种情况:
1.文件描述符
2. 外部自定义回调函数可以来清理内存
3nginx内存池原理_第6张图片
举例:对资源进行释放,在调用内存池销毁函数时,将内存池中清理链表中的函数都执行一遍
nginx内存池原理_第7张图片

你可能感兴趣的:(网络编程,nginx,内存管理,内存优化,服务器)