Ngnix 源码学习(3)----内存池结构

本文介绍了Nginx中内存池的基本结构及其作用,包括减少内存碎片和提高内存分配效率等,并详细解释了其内部数据结构如链表、内存池链表节点、大数据池等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇首先把 内存池结构 大概的说一下,具体使用将在下一节细致描述

首先知道内存池的作用

为什么需要内存池?

a. 在大量的小块内存的申请和释放的时候,能更快地进行内存分配(对比malloc和free)

b.减少内存碎片,防止内存泄露。

内存池的原理

内存池的原理非常简单,用申请一块较大的内存来代替N多的小内存块,当有需要malloc一块

比较小的内存是,直接拿这块大的内存中的地址来用即可。

当然,这样处理的缺点也是很明显的,申请一块大的内存必然会导致内存空间的浪费,但是

比起频繁地malloc和free,这样做的代价是非常小的,这是典型的以空间换时间。

Ngnix的内存池使用的数据结构是链表。

首先

typedef struct ngx_pool_s        ngx_pool_t;


我们知道以上定义 其结构体是什么样的呢?

struct ngx_pool_s {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *current;
    ngx_chain_t          *chain;
    ngx_pool_t           *next;
    ngx_pool_large_t     *large;
    ngx_pool_cleanup_t   *cleanup;
    ngx_log_t            *log;
};

以上是0。5版本的,1.0版本有些改变



struct ngx_pool_s {
    ngx_pool_data_t       d;//表示数据区域
    size_t                       max;//内存池能容纳数据的大小
    ngx_pool_t *             current;//当前内存池块(nginx中的内存池是又一连串的内存池链表组成的)
    ngx_chain_t*             chain;//主要为了将内存池连接起来
    ngx_pool_large_t*      large;//大块的数据
    ngx_pool_cleanup_t*  cleanup;//清理函数
    ngx_log_t*                 log;//写log
};


typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;


但是原理是一样的,他把两个地址进行封装了struct

看了这个结构,我们想知道这个结构到底是什么样的,他的每个数据字段什么用呢?

再把其他的数据结构贴上来。

typedef struct ngx_chain_s       ngx_chain_t;

struct ngx_chain_s {
    ngx_buf_t    *buf;
    ngx_chain_t  *next;
};

这个一个 内存池的链表

而其中的

typedef struct ngx_buf_s  ngx_buf_t;
struct ngx_buf_s {
    u_char          *pos;
    u_char          *last;
    off_t            file_pos;
    off_t            file_last;

    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;
    ngx_buf_t       *shadow;


    /* the buf's content could be changed */
    unsigned         temporary:1;

    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    unsigned         recycled:1;
    unsigned         in_file:1;
    unsigned         flush:1;
    unsigned         sync:1;
    unsigned         last_buf:1;
    unsigned         last_in_chain:1;

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    unsigned         zerocopy_busy:1;

    /* STUB */ int   num;
};


下面是一个 大数据池,当申请的内存不够用的时候,就使用大内存。

typedef struct ngx_pool_large_s  ngx_pool_large_t;
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;
    void                 *alloc;
};
typedef struct {
    ngx_fd_t              fd;
    u_char               *name;
    ngx_log_t            *log;
} ngx_pool_cleanup_file_t;

struct ngx_log_s {
    ngx_uint_t           log_level;
    ngx_open_file_t     *file;

    ngx_atomic_uint_t    connection;

    ngx_log_handler_pt   handler;
    void                *data;

    /*
     * we declare "action" as "char *" because the actions are usually
     * the static strings and in the "u_char *" case we have to override
     * their types all the time
     */

    char                *action;
};

下面的是用来清理内存的。

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


以上是起数据元素了,直接用代码可能看不懂,但是你要画出来就可能明白了

如下图所示

今天只是简单介绍了内存的大概结构,下面一篇文章将介绍如何使用内存池

更多文章欢迎访问:http://blog.youkuaiyun.com/wallwind

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值