search

1. Source code location

Header file: http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_palloc.h

Source file: http://trac.nginx.org/ nginx/browser/nginx/src/core/ngx_palloc.c

2. Data structure definition

Let’s first learn about several main data structures of nginx memory pool:

ngx_pool_data_t (memory pool data block structure)

1:typedef struct { 2:     u_char               *last;        3:     u_char               *end; 4:     ngx_pool_t           *next; 5:     ngx_uint_t            failed; 6: } ngx_pool_data_t;
  • last: It is an unsigned char type pointer, which saves the last address allocated to the current memory pool, that is, the next allocation starts here.
  • end: The end position of the memory pool;
  • next: There are many blocks of memory in the memory pool. These memory blocks are connected into a linked list through this pointer, and next points to the next block of memory.
  • failed: The number of memory pool allocation failures.

ngx_pool_s (memory pool header structure)

1:struct ngx_pool_s { 2:     ngx_pool_data_t       d; 3:     size_t                max; 4:     ngx_pool_t           *current; 5:     ngx_chain_t          *chain; 6:     ngx_pool_large_t     *large; 7:     ngx_pool_cleanup_t   *cleanup; 8:     ngx_log_t            *log; 9: };
  • d: the data block of the memory pool;
  • max: the maximum value of the memory pool data block;
  • current: points to the current memory pool;
  • chain: This pointer is attached to an ngx_chain_t structure;
  • large: a large memory linked list, which is used when the allocated space exceeds max;
  • cleanup: callback to release the memory pool
  • log: log information

is composed of ngx_pool_data_t and ngx_pool_t The composed nginx memory pool structure is shown in the figure below:

Nginx memory management

3. Introduction to related functions

Before analyzing the memory pool method, we need to introduce several main memory-related functions:

ngx_alloc: (just对malloc进行了简单的封装)

1:void * 2: ngx_alloc(size_t size, ngx_log_t *log) 3: { 4:     void  *p; 5:  6:     p = malloc(size); 7:     if (p == NULL) { 8:         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, 9:                       "malloc(%uz) failed", size); 10:     } 11:  12:     ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size); 13:  14:     return p; 15: }

ngx_calloc:(调用malloc并初始化为0)

1:void * 2: ngx_calloc(size_t size, ngx_log_t *log) 3: { 4:     void  *p; 5:  6:     p = ngx_alloc(size, log); 7:  8:     if (p) { 9:         ngx_memzero(p, size); 10:     } 11:  12:     return p; 13: }

ngx_memzero:

1: #define ngx_memzero(buf, n)       (void) memset(buf, 0, n)

ngx_free :

1: #define ngx_free          free

ngx_memalign:

1:void * 2: ngx_memalign(size_t alignment, size_t size, ngx_log_t *log) 3: { 4:     void  *p; 5:     int    err; 6:  7:     err = posix_memalign(&p, alignment, size); 8:  9:     if (err) { 10:         ngx_log_error(NGX_LOG_EMERG, log, err, 11:                       "posix_memalign(%uz, %uz) failed", alignment, size); 12:         p = NULL; 13:     } 14:  15:     ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0, 16:                    "posix_memalign: %p:%uz @%uz", p, size, alignment);rrree
The alignment here is mainly for some unix platforms that require dynamic alignment. It encapsulates posix_memalign() provided by POSIX 1003.1d. In most cases, In this case, the compiler and C library transparently handle the alignment problem for you. nginx is controlled through the macro NGX_HAVE_POSIX_MEMALIGN; calling posix_memalign( ) successfully will return sizebytes of dynamic memory, and the address of this memory is a multiple of alignment. The parameter alignment must be a power of 2, or a multiple of the size of the void pointer. The address of the returned memory block is placed in memptr, and the function return value is 0
.

4. Basic operations of the memory pool🎜
  • The main external methods of the memory pool are:
void * ngx_pnalloc(ngx_pool_t *pool, size_t size);ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
Create a memory pool ngx_pool_t * ngx_create_pool(size_t size, ngx_log_t *log);
Destroy the memory pool vo id ngx_destroy_pool(ngx_pool_t *pool ; ( Not aligned)
Memory clearing

4.1 创建内存池ngx_create_pool

ngx_create_pool用于创建一个内存池,我们创建时,传入我们的需要的初始大小:

1: ngx_pool_t * 2: ngx_create_pool(size_t size, ngx_log_t *log) 3: { 4:     ngx_pool_t  *p; 5:     6:     //以16(NGX_POOL_ALIGNMENT)字节对齐分配size内存 7:     p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log); 8:     if (p == NULL) { 9:         return NULL; 10:     } 11:  12:     //初始状态:last指向ngx_pool_t结构体之后数据取起始位置 13:     p->d.last = (u_char *) p + sizeof(ngx_pool_t); 14:     //end指向分配的整个size大小的内存的末尾 15:     p->d.end = (u_char *) p + size; 16:     17:     p->d.next = NULL; 18:     p->d.failed = 0; 19:  20:     size = size - sizeof(ngx_pool_t); 21:     //#define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1),内存池最大不超过4095,x86中页的大小为4K 22:     p->max = (size 23:  24:     p->current = p; 25:     p->chain = NULL; 26:     p->large = NULL; 27:     p->cleanup = NULL; 28:     p->log = log; 29:  30:     return p; 31: }

nginx对内存的管理分为大内存与小内存,当某一个申请的内存大于某一个值时,就需要从大内存中分配空间,否则从小内存中分配空间。

nginx中的内存池是在创建的时候就设定好了大小,在以后分配小块内存的时候,如果内存不够,则是重新创建一块内存串到内存池中,而不是将原有的内存池进行扩张。当要分配大块内存是,则是在内存池外面再分配空间进行管理的,称为大块内存池。

 

4.2 内存申请 ngx_palloc

1:void * 2: ngx_palloc(ngx_pool_t *pool, size_t size) 3: { 4:     u_char      *m; 5:     ngx_pool_t  *p; 6:  7:     //如果申请的内存大小小于内存池的max值 8:     if (size max) { 9:  10:         p = pool->current; 11:  12:         do { 13:             //对内存地址进行对齐处理 14:             m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT); 15:  16:             //如果当前内存块够分配内存,则直接分配 17:             if ((size_t) (p->d.end - m) >= size) 18:             { 19:                 p->d.last = m + size; 20:  21:                 return m; 22:             } 23:             24:             //如果当前内存块有效容量不够分配,则移动到下一个内存块进行分配 25:             p = p->d.next; 26:  27:         } while (p); 28:  29:         //当前所有内存块都没有空闲了,开辟一块新的内存,如下2详细解释 30:         return ngx_palloc_block(pool, size); 31:     } 32:  33:     //分配大块内存 34:     return ngx_palloc_large(pool, size); 35: }

需要说明的几点:

1、ngx_align_ptr,这是一个用来内存地址取整的宏,非常精巧,一句话就搞定了。作用不言而喻,取整可以降低CPU读取内存的次数,提高性能。因为这里并没有真正意义调用malloc等函数申请内存,而是移动指针标记而已,所以内存对齐的活,C编译器帮不了你了,得自己动手。

1: #define ngx_align_ptr(p, a)                                                   \ 2:      (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))

2、开辟一个新的内存块 ngx_palloc_block(ngx_pool_t *pool, size_t size)

这个函数是用来分配新的内存块,为pool内存池开辟一个新的内存块,并申请使用size大小的内存;

1:static void * 2: ngx_palloc_block(ngx_pool_t *pool, size_t size) 3: { 4:     u_char      *m; 5:     size_t       psize; 6:     ngx_pool_t  *p, *new; 7:  8:     //计算内存池第一个内存块的大小 9:     psize = (size_t) (pool->d.end - (u_char *) pool); 10:  11:     //分配和第一个内存块同样大小的内存块 12:     m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); 13:     if (m == NULL) { 14:         return NULL; 15:     } 16:  17:     new = (ngx_pool_t *) m; 18:  19:     //设置新内存块的end 20:     new->d.end = m + psize; 21:     new->d.next = NULL; 22:     new->d.failed = 0; 23:  24:     //将指针m移动到d后面的一个位置,作为起始位置 25:     m += sizeof(ngx_pool_data_t); 26:     //对m指针按4字节对齐处理 27:     m = ngx_align_ptr(m, NGX_ALIGNMENT); 28:     //设置新内存块的last,即申请使用size大小的内存 29:     new->d.last = m + size; 30:  31:     //这里的循环用来找最后一个链表节点,这里failed用来控制循环的长度,如果分配失败次数达到5次,就忽略,不需要每次都从头找起 32:     for (p = pool->current; p->d.next; p = p->d.next) { 33:         if (p->d.failed++ > 4) { 34:             pool->current = p->d.next; 35:         } 36:     } 37:  38:     p->d.next = new; 39:  40:     return m; 41: }

3、分配大块内存 ngx_palloc_large(ngx_pool_t *pool, size_t size)

在ngx_palloc中首先会判断申请的内存大小是否超过内存块的最大限值,如果超过,则直接调用ngx_palloc_large,进入大内存块的分配流程;

1:static void * 2: ngx_palloc_large(ngx_pool_t *pool, size_t size) 3: { 4:     void              *p; 5:     ngx_uint_t         n; 6:     ngx_pool_large_t  *large; 7:  8:     // 直接在系统堆中分配一块大小为size的空间 9:     p = ngx_alloc(size, pool->log); 10:     if (p == NULL) { 11:         return NULL; 12:     } 13:  14:     n = 0; 15:  16:     // 查找到一个空的large区,如果有,则将刚才分配的空间交由它管理  17:     for (large = pool->large; large; large = large->next) { 18:         if (large->alloc == NULL) { 19:             large->alloc = p; 20:             return p; 21:         } 22:         //为了提高效率, 如果在三次内没有找到空的large结构体,则创建一个 23:         if (n++ > 3) { 24:             break; 25:         } 26:     } 27:  28:  29:     large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); 30:     if (large == NULL) { 31:         ngx_free(p); 32:         return NULL; 33:     } 34:     35:     //将large链接到内存池 36:     large->alloc = p; 37:     large->next = pool->large; 38:     pool->large = large; 39:  40:     return p; 41: }

整个内存池分配如下图:

Nginx memory management

  • 4.3 内存池重置 ngx_reset_pool

1:void 2: ngx_reset_pool(ngx_pool_t *pool) 3: { 4:     ngx_pool_t        *p; 5:     ngx_pool_large_t  *l; 6:     7:     //释放大块内存 8:     for (l = pool->large; l; l = l->next) { 9:         if (l->alloc) { 10:             ngx_free(l->alloc); 11:         } 12:     } 13:     14:     // 重置所有小块内存区 15:     for (p = pool; p; p = p->d.next) { 16:         p->d.last = (u_char *) p + sizeof(ngx_pool_t); 17:         p->d.failed = 0; 18:     } 19:  20:     pool->current = pool; 21:     pool->chain = NULL; 22:     pool->large = NULL; 23: }

4.4 内存池释放 ngx_pfree

1: ngx_int_t 2: ngx_pfree(ngx_pool_t *pool, void *p) 3: { 4:     ngx_pool_large_t  *l; 5:  6:     //只检查是否是大内存块,如果是大内存块则释放 7:     for (l = pool->large; l; l = l->next) { 8:         if (p == l->alloc) { 9:             ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, 10:                            "free: %p", l->alloc); 11:             ngx_free(l->alloc); 12:             l->alloc = NULL; 13:  14:             return NGX_OK; 15:         } 16:     } 17: 

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
The Continued Use of PHP: Reasons for Its EnduranceThe Continued Use of PHP: Reasons for Its EnduranceApr 19, 2025 am 12:23 AM

What’s still popular is the ease of use, flexibility and a strong ecosystem. 1) Ease of use and simple syntax make it the first choice for beginners. 2) Closely integrated with web development, excellent interaction with HTTP requests and database. 3) The huge ecosystem provides a wealth of tools and libraries. 4) Active community and open source nature adapts them to new needs and technology trends.

PHP and Python: Exploring Their Similarities and DifferencesPHP and Python: Exploring Their Similarities and DifferencesApr 19, 2025 am 12:21 AM

PHP and Python are both high-level programming languages ​​that are widely used in web development, data processing and automation tasks. 1.PHP is often used to build dynamic websites and content management systems, while Python is often used to build web frameworks and data science. 2.PHP uses echo to output content, Python uses print. 3. Both support object-oriented programming, but the syntax and keywords are different. 4. PHP supports weak type conversion, while Python is more stringent. 5. PHP performance optimization includes using OPcache and asynchronous programming, while Python uses cProfile and asynchronous programming.

PHP and Python: Different Paradigms ExplainedPHP and Python: Different Paradigms ExplainedApr 18, 2025 am 12:26 AM

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

PHP and Python: A Deep Dive into Their HistoryPHP and Python: A Deep Dive into Their HistoryApr 18, 2025 am 12:25 AM

PHP originated in 1994 and was developed by RasmusLerdorf. It was originally used to track website visitors and gradually evolved into a server-side scripting language and was widely used in web development. Python was developed by Guidovan Rossum in the late 1980s and was first released in 1991. It emphasizes code readability and simplicity, and is suitable for scientific computing, data analysis and other fields.

Choosing Between PHP and Python: A GuideChoosing Between PHP and Python: A GuideApr 18, 2025 am 12:24 AM

PHP is suitable for web development and rapid prototyping, and Python is suitable for data science and machine learning. 1.PHP is used for dynamic web development, with simple syntax and suitable for rapid development. 2. Python has concise syntax, is suitable for multiple fields, and has a strong library ecosystem.

PHP and Frameworks: Modernizing the LanguagePHP and Frameworks: Modernizing the LanguageApr 18, 2025 am 12:14 AM

PHP remains important in the modernization process because it supports a large number of websites and applications and adapts to development needs through frameworks. 1.PHP7 improves performance and introduces new features. 2. Modern frameworks such as Laravel, Symfony and CodeIgniter simplify development and improve code quality. 3. Performance optimization and best practices further improve application efficiency.

PHP's Impact: Web Development and BeyondPHP's Impact: Web Development and BeyondApr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

How does PHP type hinting work, including scalar types, return types, union types, and nullable types?How does PHP type hinting work, including scalar types, return types, union types, and nullable types?Apr 17, 2025 am 12:25 AM

PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Tools

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.