Memory pool module of nginx

Structural drawing

Use

  • Allocate the size of NGX pool t directly, and then allocate a certain amount of memory from it.

  • large memory allocation steps:

    • Allocate memory block of size size, and check whether there is free large in pool to link memory.
    • If not, allocate a large structure and mount its large header pointer to NGX? Pool? Data? T.
  • For example, NGX? Array? T:

    • First, the head pointer address of NGX ﹣ array ﹣ t is allocated in: NGX ﹣ pool ﹣ large ﹣ s linked list
    • In the data allocated with NGX ﹣ array ﹣ T, the address is in: NGX ﹣ pool ﹣ large ﹣ s linked list

structure

NGX? Pool? S: linked list (memory pool head pointer)
struct ngx_pool_s {
    ngx_pool_data_t       d;    'Current memory block'
    size_t                max; 'The size of all available memory, including used and unused memory. The standard to distinguish small and large memory, less than or equal to max Is small memory, greater than max Is a large block of memory.'
    ngx_pool_t           *current;  'In many ngx_pool_t In the linked list, current Point to the first traversal when allocating memory ngx_pool_t'
    ngx_chain_t          *chain;    ''
    ngx_pool_large_t     *large;    'Pointing to multiple ngx_pool_large_t Linked list'
    ngx_pool_cleanup_t   *cleanup;  'Pointing to multiple ngx_pool_cleanup_t Linked list'
    ngx_log_t            *log;
};
NGX? Pool? Data? T: memory structure (mainly used to store the head pointer address of NGX? Pool? Large? S)
typedef struct {
    u_char               *last; 'First address to unused memory'
    u_char               *end;  'Tail address to unused memory'
    ngx_pool_t           *next; 'Multiple ngx_pool_t adopt next Linked into a linked list'
    ngx_uint_t            failed;   'Whenever there is not enough space left to allocate small blocks of memory, failed Members will add 1. failed When the member is greater than 4, ngx_pool_t Of current Moves down a small memory pool.'
} ngx_pool_data_t;
NGX ﹣ pool ﹣ large ﹣ s: large memory structure (link list of actual storage structures: head pointer address storage + data memory address)
struct ngx_pool_large_s {
    ngx_pool_large_t     *next;  'Multiple ngx_pool_large_t adopt next Linked list'
    void                 *alloc; 'point ngx_alloc Allocated large memory'
};
NGX? Pool? Cleanup? S: memory cleanup list
struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler; 'Memory clearing function: typedef void (*ngx_pool_cleanup_pt)(void *data)'
    void                 *data;
    ngx_pool_cleanup_t   *next; 'Multiple ngx_pool_cleanup_t adopt next Linked list'
};

Method

NGX? Create? Pool: initialization

/*
    size: Memory size
     
    NGX_MAX_ALLOC_FROM_POOL: (16 * 1024)
*/

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);    'The allocation size is size,Address aligned memory'
    if (p  NULL) {
        return NULL;
    }

    p->d.last = (u_char *) p + sizeof(ngx_pool_t);  'Unused starting address'
    p->d.end = (u_char *) p + size;                 'Unused tail address'
    p->d.next = NULL;
    p->d.failed = 0;

    size = size - sizeof(ngx_pool_t);       'Subtract the size of the memory pool information'
    'NGX_MAX_ALLOC_FROM_POOL: ngx_pagesize - 1 '
    'ngx_pagesize :Memory paging for '
    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;
}
  • Characteristic:

    • Allocate a memory pool of size,
    • The real data size is: size - sizeof (NGX? Pool? T)
NGX? Destroy? Pool: release
void
ngx_destroy_pool(ngx_pool_t *pool)
{
    ngx_pool_t          *p, *n;
    ngx_pool_large_t    *l;
    ngx_pool_cleanup_t  *c;
    //Call memory handler handler handler
    for (c = pool->cleanup; c; c = c->next) {
        if (c->handler) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "run cleanup: %p", c);
            c->handler(c->data);
        }
    }

    for (l = pool->large; l; l = l->next) {
        if (l->alloc) {
            ngx_free(l->alloc); 'Free up large memory'
        }
    }

    for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) {
        ngx_free(p);

        if (n  NULL) {
            break;
        }
    }
}

NGX? Reset? Pool: reset
void
ngx_reset_pool(ngx_pool_t *pool)
{
    ngx_pool_t        *p;
    ngx_pool_large_t  *l;

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

    for (p = pool; p; p = p->d.next) {
        p->d.last = (u_char *) p + sizeof(ngx_pool_t);
        p->d.failed = 0;
    }

    pool->current = pool;
    pool->chain = NULL;
    pool->large = NULL;
}
NGX ﹐ palloc, NGX ﹐ pnalloc, NGX ﹐ palloc ﹐ small, NGX ﹐ palloc ﹐ block, NGX ﹐ palloc ﹐ large, NGX ﹐ pmemalign: allocation space
  • Characteristic:

    • NGX ﹣ palloc: allocate large blocks of memory
    • NGX? Pnalloc: allocate large blocks of memory
    • NGX ﹐ palloc ﹐ large: allocate size memory and mount it in empty large memory. If there is no empty, call NGX? Palloc? Small to create a new structure pointer of NGX? Pool? Large? S
    • NGX ﹣ palloc ﹣ small: allocate size memory, and hang it under NGX ﹣ pool ﹣ data ﹣ t. If not, call NGX? Palloc? Block
    • NGX pool data block: allocate a new NGX pool data block to mount in the memory pool
    • NGX pmemalign: allocate a memory aligned NGX pulloc large in the large linked list

void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 1);
    }
#endif

    return ngx_palloc_large(pool, size);
}


void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 0);
    }
#endif

    return ngx_palloc_large(pool, size);
}

/**
    Detect allocation block address
*/

static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
    void              *p;
    ngx_uint_t         n;
    ngx_pool_large_t  *large;

    p = ngx_alloc(size, pool->log); 'distribution size Size space'
    if (p  NULL) {
        return NULL;
    }

    n = 0;
    //If there is an existing large memory block header pointer, no space is allocated. Then assign it
    for (large = pool->large; large; large = large->next) {
        if (large->alloc  NULL) {
            large->alloc = p;
            return p;
        }

        if (n++ > 3) {
            break;
        }
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);    'Allocate a new large memory block's head pointer'
    if (large  NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}

/*
    Traverse the linked list, and check whether the memory is not allocated to allocate the data
    pool: Memory pool structure
    size: 
*/
static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)
{
    u_char      *m;
    ngx_pool_t  *p;

    p = pool->current;  'Currently set to new'
    'ergodic ngx_pool_t Linked list, allocation size is size Small chunks of memory'
    do {
        m = p->d.last;  

        if (align) {
            m = ngx_align_ptr(m, NGX_ALIGNMENT);    'alignment d.last'
        }

        if ((size_t) (p->d.end - m) >= size) {  'If end-last>size,Then allocate memory'
            p->d.last = m + size;   'Unassigned address header+Allocated memory address'

            return m;
        }

        p = p->d.next;  'Next'

    } while (p);    'Next not for null'

    return ngx_palloc_block(pool, size);    'Size not found size Insert a ngx_pool_t,The allocation size is size Small chunks of memory'
}

/**
    Assign small block address
*/

static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t  *p, *new;

    psize = (size_t) (pool->d.end - (u_char *) pool);   'Allocate memory address tail for- ngx_pool_t Get the real data storage address'

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); 'distribution size Size of, memory address alignment'
    if (m  NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m; 'The new size is size Memory address of(Inclusive ngx_pool_t Size)'

    new->d.end = m + psize; 'Double assigned address'
    new->d.next = NULL;
    new->d.failed = 0;

    m += sizeof(ngx_pool_data_t);
    m = ngx_align_ptr(m, NGX_ALIGNMENT);
    new->d.last = m + size;

    for (p = pool->current; p->d.next; p = p->d.next) {
        if (p->d.failed++ > 4) {
            pool->current = p->d.next;
        }
    }

    p->d.next = new;

    return m;
}

void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
    void              *p;
    ngx_pool_large_t  *large;

    p = ngx_memalign(alignment, size, pool->log);
    if (p  NULL) {
        return NULL;
    }

    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large  NULL) {
        ngx_free(p);
        return NULL;
    }

    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}

Free memory: ngx_pfree
ngx_int_t
ngx_pfree(ngx_pool_t *pool, void *p)
{
    ngx_pool_large_t  *l;

    for (l = pool->large; l; l = l->next) {
        if (p  l->alloc) {
            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
                           "free: %p", l->alloc);
            ngx_free(l->alloc);
            l->alloc = NULL;

            return NGX_OK;
        }
    }

    return NGX_DECLINED;
}

Tags: less

Posted on Mon, 30 Mar 2020 08:30:41 -0700 by AjithTV