os/unix/ngx_alloc.c(h)源代码分析
本文我们主要分析一下nginx内存分配的相关实现源代码。
1. os/unix/ngx_alloc.h头文件
头文件内容如下:
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */
#ifndef _NGX_ALLOC_H_INCLUDED_
#define _NGX_ALLOC_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
void *ngx_alloc(size_t size, ngx_log_t *log);
void *ngx_calloc(size_t size, ngx_log_t *log);
#define ngx_free          free
/*
 * Linux has memalign() or posix_memalign()
 * Solaris has memalign()
 * FreeBSD 7.0 has posix_memalign(), besides, early version's malloc()
 * aligns allocations bigger than page size at the page boundary
 */
#if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)
void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);
#else
#define ngx_memalign(alignment, size, log)  ngx_alloc(size, log)
#endif
extern ngx_uint_t  ngx_pagesize;
extern ngx_uint_t  ngx_pagesize_shift;
extern ngx_uint_t  ngx_cacheline_size;
#endif /* _NGX_ALLOC_H_INCLUDED_ */头文件中主要定义了分配内存空间的几个函数原型。在ngx_auto_config.h头文件中,我们有如下两个宏定义:
#ifndef NGX_HAVE_POSIX_MEMALIGN #define NGX_HAVE_POSIX_MEMALIGN 1 #endif #ifndef NGX_HAVE_MEMALIGN #define NGX_HAVE_MEMALIGN 1 #endif
对于Linux操作系统其一般支持memalign()或posix_memalign();对于solaris一般支持memalign; 对于freebsd7.0一般支持posix_memalign。
因此,这里对于有对齐要求的内存分配,其函数原型如下:
void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);如下三个变量均定义在os/unix/ngx_alloc.c源文件中:
extern ngx_uint_t ngx_pagesize; extern ngx_uint_t ngx_pagesize_shift; extern ngx_uint_t ngx_cacheline_size;
2. os/unix/ngx_alloc.c源文件
源文件内容如下:
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */
#include <ngx_config.h>
#include <ngx_core.h>
ngx_uint_t  ngx_pagesize;
ngx_uint_t  ngx_pagesize_shift;
ngx_uint_t  ngx_cacheline_size;
void *
ngx_alloc(size_t size, ngx_log_t *log)
{
    void  *p;
    p = malloc(size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "malloc(%uz) failed", size);
    }
    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
    return p;
}
void *
ngx_calloc(size_t size, ngx_log_t *log)
{
    void  *p;
    p = ngx_alloc(size, log);
    if (p) {
        ngx_memzero(p, size);
    }
    return p;
}
#if (NGX_HAVE_POSIX_MEMALIGN)
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_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }
    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "posix_memalign: %p:%uz @%uz", p, size, alignment);
    return p;
}
#elif (NGX_HAVE_MEMALIGN)
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    p = memalign(alignment, size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "memalign(%uz, %uz) failed", alignment, size);
    }
    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "memalign: %p:%uz @%uz", p, size, alignment);
    return p;
}
#endif2.1 ngx_alloc()函数
ngx_alloc()函数较为简单,直接调用malloc()函数分配指定大小的内存空间。
2.2 ngx_calloc()函数
ngx_calloc()函数首先调用ngx_alloc()函数分配中指定大小的内存空间,然后将这块分配的内存空间都清0。这里ngx_memzero()函数是在src/core/ngx_string.h头文件中定义:
#define ngx_memzero(buf, n)       (void) memset(buf, 0, n)2.3 ngx_memalign()函数实现-版本1
在宏定义NGX_HAVE_POSIX_MEMALIGN为真时,其实现如下:
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_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }
    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "posix_memalign: %p:%uz @%uz", p, size, alignment);
    return p;
}posix_memalign()函数原型如下:
int posix_memalign(void **memptr, size_t alignment, size_t size);
其会分配size字节大小的内存,并将该块内存的首地址存放于memptr中。所分配的内存首地址必须为alignment的整数倍,并且必须是2^N,还必须是sizeof(void *)的整数倍。假若size为0的话,memptr会返回为NULL。该函数存在于
注意:posix_memalign()会检查alignment参数是否满足对其要求,即必须为2^N,并且还必须是sizeof(void *)的整数倍。
2.4 ngx_memalign()函数实现-版本2
在宏定义NGX_HAVE_MEMALIGN为真时,其实现如下:
void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    p = memalign(alignment, size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "memalign(%uz, %uz) failed", alignment, size);
    }
    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "memalign: %p:%uz @%uz", p, size, alignment);
    return p;
}memalign()函数原型如下:
void *memalign(size_t alignment, size_t size);
memalign()函数是一个过时函数,其会分配size大小的内存并返回。所分配的内存首地址必须为alignment的整数倍,并且必须为2^N幂。该函数存在于
注意: memalign()可能并不会检查alignment的值是否满足对齐要求,即应为2^N.

