Nginx --- 内存分配

作者:hahaya
日期:2014-06-06

Nginx内存分配的源码主要位于${NGX_ROOT}/src/os/unix/ngx_alloc{.h|.c}文件中,Nginx提供ngx_alloc、ngx_calloc和ngx_memalign三个内存分配相关的函数,其中ngx_alloc和ngx_calloc是对系统malloc函数的封装,ngx_memalign在Linux系统下是对系统posix_memalign函数的封装,而在Solaris系统下是对系统memalign函数的封装,在其他系统下则是对ngx_alloc的define。既然Nginx提供了内存分配的函数,同样相应的也提供了内存释放的函数ngx_free,ngx_free仅仅是对系统函数free的define,因为malloc、posix_memalign、memalign分配的内存都是通过free函数释放的。

ngx_alloc.h

  1. /*

  2. * Copyright (C) Igor Sysoev

  3. * Copyright (C) Nginx, Inc.

  4. */

  5. #ifndef _NGX_ALLOC_H_INCLUDED_

  6. #define _NGX_ALLOC_H_INCLUDED_

  7. #include <ngx_config.h>

  8. #include <ngx_core.h>

  9. void *ngx_alloc(size_t size, ngx_log_t *log); /* 分配内存 不进行初始化 */

  10. void *ngx_calloc(size_t size, ngx_log_t *log); /* 分配内存 并自动初始化内存空间为0 */

  11. #define ngx_free free /* 释放内存 */

  12. /*

  13. * Linux has memalign() or posix_memalign()

  14. * Solaris has memalign()

  15. * FreeBSD 7.0 has posix_memalign(), besides, early version's malloc()

  16. * aligns allocations bigger than page size at the page boundary

  17. */

  18. /*

  19. * 封装 posix_memalign,如果是 Solaris 则封装 memalign

  20. * 根据当前电脑配置自动生成NGX_HAVE_MEMALIGN NGX_HAVE_POSIX_MEMALIGN宏

  21. * 包含顺序为${NGX_ROOT}/src/core/ngx_config.h -> ${NGX_ROOT}/objs/ngx_auto_headers.h

  22. * ngx_auto_headers.h中判断操作系统的相关类型等 根据不同的系统包含不同的系统头文件

  23. * 测试机器为Linux 故接着通过ngx_config.h包含 ${NGX_ROOT}/src/os/unixngx_linux_config.h

  24. * 接着包含${NGX_ROOT}/objs/ngx_auto_config.h

  25. *

  26. * note:ngx_auto_headers.h和ngx_auto_config.h文件是在配置Nginx过程中生成的(./configure过程)

  27. */

  28. #if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)

  29. /*

  30. * 内存分配对齐

  31. */

  32. void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);

  33. #else

  34. /*

  35. * 其他系统下,如果不存在内存分配对齐函数memalign()或posix_memalign 则直接使用ngx_alloc代替

  36. */

  37. #define ngx_memalign(alignment, size, log) ngx_alloc(size, log)

  38. #endif

  39. /*

  40. * 声明三个外部使用的变量

  41. * 全局变量ngx_alloc.c中定义 ${NGX_ROOT}/src/os/unix/ngx_posix_init.c中初始化

  42. * 为了方便后面内存池等需要内存分配的地方使用而不用每次extern

  43. * 即避免每个需要使用的文件中extern这三个变量 故放在ngx_malloc.h中

  44. */

  45. extern ngx_uint_t ngx_pagesize; /* 页大小 */

  46. extern ngx_uint_t ngx_pagesize_shift; /* 页大小对应的移位数 */

  47. extern ngx_uint_t ngx_cacheline_size; /* 缓存大小 */

  48. #endif /* _NGX_ALLOC_H_INCLUDED_ */

ngx_alloc.c

  1. /*

  2. * Copyright (C) Igor Sysoev

  3. * Copyright (C) Nginx, Inc.

  4. */

  5. #include <ngx_config.h>

  6. #include <ngx_core.h>

  7. /* 三个变量的定义 */

  8. ngx_uint_t ngx_pagesize;

  9. ngx_uint_t ngx_pagesize_shift;

  10. ngx_uint_t ngx_cacheline_size;

  11. /*

  12. * 分配内存 主要是对系统函数malloc的封装

  13. * 增加分配内存失败的判断机制 内存分配失败时写入日志文件

  14. */

  15. void *

  16. ngx_alloc(size_t size, ngx_log_t *log)

  17. {

  18. void *p;

  19. /* 调用malloc分配内存 */

  20. p = malloc(size);

  21. /* 分配内存失败 将错误信息写入日志文件 */

  22. if (p == NULL) {

  23. ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,

  24. "malloc(%uz) failed", size);

  25. }

  26. /* DEBUG模式下的处理 */

  27. ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);

  28. return p;

  29. }

  30. /*

  31. * 分配内存 并将分配的内存初始化为0

  32. * 封装ngx_alloc之后调用ngx_memzero初始化内存为0

  33. */

  34. void *

  35. ngx_calloc(size_t size, ngx_log_t *log)

  36. {

  37. void *p;

  38. //分配内存

  39. p = ngx_alloc(size, log);

  40. //内存初始化

  41. if (p) {

  42. ngx_memzero(p, size);

  43. }

  44. return p;

  45. }

  46. #if (NGX_HAVE_POSIX_MEMALIGN)

  47. /*

  48. * Linux系统下调用posix_memalign进行内存分配和内存对齐

  49. *

  50. */

  51. void *

  52. ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)

  53. {

  54. void *p;

  55. int err;

  56. /*

  57. * 背景:

  58. * 1)POSIX 1003.1d

  59. * 2)POSIX 标明了通过malloc( ), calloc( ), 和 realloc( ) 返回的地址对于任何的C类型来说都是对齐的

  60. * 功能:由posix_memalign分配的内存空间,需要由free释放。

  61. * 参数:

  62. * p 分配好的内存空间的首地址

  63. * alignment 对齐边界,Linux中,32位系统是8字节,64位系统是16字节

  64. * size 指定分配size字节大小的内存

  65. * 要求:

  66. * 1)要求alignment是2的幂,并且是p指针大小的倍数

  67. * 2)要求size是alignment的倍数

  68. * 返回:

  69. * 0 成功

  70. * EINVAL 参数不满足要求

  71. * ENOMEM 内存分配失败

  72. * 注意:

  73. * 1)该函数不影响errno,只能通过返回值判

  74. * 2)在32位系统下malloc、calloc分配的内存是8字节为边界对齐的 即返回的内存地址起始值是8的倍数

  75. * 3)在64位系统下malloc、calloc分配的内存时16字节为边界对齐的 即返回的内存地址起始值是16的倍数

  76. * 4)有时候,对齐更大的边界,例如页面等,程序员需要动态的对齐,于是出现了posix_memalign函数

  77. * 5)posix_memalign函数分配内存返回的内存地址起始值是alignment的倍数

  78. */

  79. err = posix_memalign(&p, alignment, size);

  80. /* 内存分配失败 */

  81. if (err) {

  82. ngx_log_error(NGX_LOG_EMERG, log, err,

  83. "posix_memalign(%uz, %uz) failed", alignment, size);:w

  84. p = NULL;

  85. }

  86. ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,

  87. "posix_memalign: %p:%uz @%uz", p, size, alignment);

  88. return p;

  89. }

  90. #elif (NGX_HAVE_MEMALIGN)

  91. /*

  92. * Solaris系统下调用memalign进行内存分配和内存对齐

  93. *

  94. */

  95. void *

  96. ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)

  97. {

  98. void *p;

  99. p = memalign(alignment, size);

  100. /* 内存分配失败 */

  101. if (p == NULL) {

  102. ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,

  103. "memalign(%uz, %uz) failed", alignment, size);

  104. }

  105. ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,

  106. "memalign: %p:%uz @%uz", p, size, alignment);

  107. return p;

  108. }

  109. #endif

为了方便测试和学习Nginx的内存分配,以免引入过多的文件,没有使用Nginx中的文件包含机制,去掉了出现分配错误后写入日志文件的操作,并且只关注Linux系统,测试代码如下:
ngx_alloc.h

  1. #ifndef _NGX_ALLOC_H_INCLUDE_

  2. #define _NGX_ALLOC_H_INCLUDE_

  3. #include <stdio.h>

  4. #include <stdlib.h>

  5. #include <memory.h>

  6. /* 分配内存 */

  7. void *ngx_alloc(size_t size);

  8. void *ngx_calloc(size_t size);

  9. void *ngx_memalign(size_t alignment, size_t size);

  10. /* 释放内存 */

  11. #define ngx_free free

  12. #endif

ngx_alloc.c

  1. #include "ngx_alloc.h"

  2. void *ngx_alloc(size_t size)

  3. {

  4. void *p;

  5. p = malloc(size);

  6. if (NULL == p) {

  7. printf("malloc %d memory failed.\n", (int)size);

  8. } else {

  9. printf("malloc %d memory success.\n", (int)size);

  10. }

  11. return p;

  12. }

  13. void *ngx_calloc(size_t size)

  14. {

  15. void *p;

  16. p = ngx_alloc(size);

  17. if (p) {

  18. memset(p, 0, size);

  19. }

  20. return p;

  21. }

  22. void *ngx_memalign(size_t alignment, size_t size)

  23. {

  24. void *p;

  25. int err;

  26. err = posix_memalign(&p, alignment, size);

  27. if (err) {

  28. printf("posix_memalign %d memory failed.\n", (int)size);

  29. p = NULL;

  30. } else {

  31. printf("posix_memalign %d memory success.\n", (int)size);

  32. }

  33. return p;

  34. }

ngx_alloc_test.c

  1. #include "ngx_alloc.h"

  2. int main()

  3. {

  4. //ngx_alloc

  5. void *p_alloc = ngx_alloc(100);

  6. printf("p_alloc address:%X\n", p_alloc);

  7. ngx_free(p_alloc);

  8. //ngx_calloc

  9. char *p_calloc = (char*)ngx_calloc(100);

  10. printf("p_calloc address:%X\n", p_calloc);

  11. ngx_free(p_calloc);

  12. //ngx_memalign

  13. void *p_memalign = ngx_memalign(32, 1024);

  14. printf("p_memalign address:%X\n", p_memalign);

  15. ngx_free(p_memalign);

  16. return 0;

  17. }

makefile

  1. cc = gcc

  2. target = ngx_alloc_test

  3. objs = ngx_alloc.o ngx_alloc_test.o

  4. $(target):$(objs)

  5. $(cc) $(objs) -o $(target)

  6. ngx_alloc.o:ngx_alloc.h ngx_alloc.c

  7. $(cc) -c -w ngx_alloc.c

  8. ngx_alloc_test.o:ngx_alloc_test.c

  9. $(cc) -c -w ngx_alloc_test.c

  10. clean:

  11. rm $(target) $(objs)

<<使用cJSON解析JSON数据

首页 - Wiki
Copyright © 2011-2025 iteam. Current version is 2.148.1. UTC+08:00, 2025-11-24 08:09
浙ICP备14020137号-1 $访客地图$