当前位置:Gxlcms > PHP教程 > Nginx源码分析(1)之——共享内存的配置、分配及初始化

Nginx源码分析(1)之——共享内存的配置、分配及初始化

时间:2021-07-01 10:21:17 帮助过:3人阅读

在Nginx里,一块完整的共享内存以数据结构ngx_shm_zone_t来封装表示。

  1. <code><span>typedef</span><span>struct</span> {
  2. u_char *addr; <span>// 分配的共享内存的实际地址(这里实际共享内存的分配,根据当前系统可提供的接口,可以调用mmap或者shmget来进行分配,具体的用法,自己man吧)</span>
  3. size_t size; <span>// 共享内存的大小</span>
  4. ngx_str_t name; <span>// 该字段用作共享内存的唯一标识,能让Nginx知道想使用哪个共享内存</span>
  5. ngx_log_t *<span>log</span>;
  6. ngx_uint_t exists; <span>/* unsigned exists:1; */</span>
  7. } ngx_shm_t;
  8. <span>typedef</span><span>struct</span> ngx_shm_zone_s ngx_shm_zone_t;
  9. <span>typedef</span> ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, <span>void</span> *data);
  10. <span>struct</span> ngx_shm_zone_s {
  11. <span>void</span> *data;
  12. ngx_shm_t shm;
  13. ngx_shm_zone_init_pt init; <span>// 这里有一个钩子函数,用于实际共享内存进行分配后的初始化</span><span>void</span> *tag; <span>// 区别于shm.name,shm.name没法让Nginx区分到底是想新创建一个共享内存,还是使用已存在的旧的共享内存</span><span>// 因此这里引入tag字段来解决该问题,tag一般指向当前模块的ngx_module_t变量,见:...</span>
  14. };</code>

要在Nginx里使用一个共享内存,需要在配置文件里加上该共享内存的相关信息(添加一条指令),如:共享内存的名称,共享内存的大小等。因此在配置解析阶段,解析到相应的指令时,会创建对应的共享内存(此时创建的仅仅是代表共享内存的结构体:ngx_shm_zone_t,真实共享内存的分配在ngx_init_cycle(&init_cycle)解析完配置后,进行实际共享内存的分配并初始化)。见:

  1. <code><span>int</span> ngx_cdecl
  2. main(<span>int</span> argc, <span>char</span> *<span>const</span> *argv) <span>// 在master进程中</span>
  3. {
  4. cycle = ngx_init_cycle(&init_cycle);
  5. {
  6. <span>if</span> (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { <span>// 解析配置</span>
  7. {
  8. 解析到http指令(进入ngx_http_block())
  9. {
  10. <span>// 会依次执行</span><span>typedef</span><span>struct</span> {
  11. ngx_int_t (*preconfiguration)(ngx_conf_t *cf); <span>/* 执行顺序4 */</span>
  12. ngx_int_t (*postconfiguration)(ngx_conf_t *cf); <span>/* 执行顺序8 */</span><span>void</span> *(*create_main_conf)(ngx_conf_t *cf); <span>/* 执行顺序1 */</span><span>char</span> *(*init_main_conf)(ngx_conf_t *cf, <span>void</span> *conf); <span>/* 执行顺序5 */</span><span>void</span> *(*create_srv_conf)(ngx_conf_t *cf); <span>/* 执行顺序2 */</span><span>char</span> *(*merge_srv_conf)(ngx_conf_t *cf, <span>void</span> *prev, <span>void</span> *conf); <span>/* 执行顺序6 */</span><span>void</span> *(*create_loc_conf)(ngx_conf_t *cf); <span>/* 执行顺序3 */</span><span>char</span> *(*merge_loc_conf)(ngx_conf_t *cf, <span>void</span> *prev, <span>void</span> *conf); <span>/* 执行顺序7 */</span>
  13. } ngx_http_module_t;
  14. 同时,还有个执行顺序<span>4.5</span>:
  15. <span>struct</span> ngx_command_s { <span>/* 执行顺序4.5 */</span>
  16. ngx_str_t name;
  17. ngx_uint_t type;
  18. <span>char</span> *(*<span>set</span>)(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf);
  19. ngx_uint_t conf;
  20. ngx_uint_t offset;
  21. <span>void</span> *post;
  22. };
  23. <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
  24. <span>if</span> (module->create_main_conf) {ctx->main_conf[mi] = module->create_main_conf(cf);}
  25. <span>if</span> (module->create_srv_conf) {ctx->srv_conf[mi] = module->create_srv_conf(cf);}
  26. <span>if</span> (module->create_loc_conf) {ctx->loc_conf[mi] = module->create_loc_conf(cf);}
  27. }
  28. <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
  29. <span>if</span> (module->preconfiguration) {<span>if</span> (module->preconfiguration(cf) != NGX_OK) {}
  30. }
  31. rv = ngx_conf_parse(cf, NULL);
  32. {
  33. <span>/*
  34. * 指令的解析
  35. * 共享内存配置相关的指令也在这里进行解析
  36. * 详细见:
  37. * ngx_shm_zone_t *
  38. * ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
  39. */</span> }
  40. <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
  41. <span>if</span> (module->init_main_conf) {rv = module->init_main_conf(cf, ctx->main_conf[mi]);}
  42. rv = ngx_http_merge_servers(cf, cmcf, module, mi);
  43. }
  44. <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
  45. <span>if</span> (module->postconfiguration) {<span>if</span> (module->postconfiguration(cf) != NGX_OK)}
  46. }
  47. }
  48. }
  49. <span>// in ngx_init_cycle(&init_cycle)</span>
  50. line: <span>462</span><span>if</span> (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) <span>/* 实际共享内存分配的地方 */</span>
  51. line: <span>466</span><span>if</span> (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK)
  52. <span>/* 共享内存管理机制的初始化
  53. * 共享内存的使用涉及另外两个主题:
  54. * 1、多进程共同使用时之间的互斥问题
  55. * 2、引入特定的使用方式(slab机制,这在下一个主题:“Nginx源码分析(2)之——共享内存管理之slab机制”中进行介绍),以提高性能
  56. */</span>
  57. line: <span>470</span><span>if</span> (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) <span>/* 分配之后的初始化 */</span>
  58. }
  59. ngx_shm_zone_t *
  60. ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, <span>void</span> *tag)
  61. {
  62. ngx_uint_t i;
  63. ngx_shm_zone_t *shm_zone;
  64. ngx_list_part_t *part;
  65. <span>/*
  66. * Nginx中所有的共享内存都以list链表的形式组织在全局变量cf->cycle->shared_memory中
  67. * 在创建新的共享内存之前,会对该链表进行遍历查找以及冲突检测,
  68. * 对于已经存在且不存在冲突时,对共享内存直接进行返回并引用
  69. * 存在且不存在冲突:共享内存的名称相同,大小相同,且tag指向的是同一个模块
  70. * 有冲突,则报错
  71. * 否则,重新分配ngx_shm_zone_t,并挂到全局链表cf->cycle->shared_memory中,最后进行结构初始化
  72. * shm_zone = ngx_list_push(&cf->cycle->shared_memory);
  73. * 至此:
  74. * 仅仅是创建了共享内存的结构体:ngx_shm_zone_t,ngx_shm_zone_t.shm.addr指向的真实共享内存并没有进行实际的分配
  75. */</span>
  76. part = &cf->cycle->shared_memory.part;
  77. shm_zone = part->elts;
  78. <span>for</span> (i = <span>0</span>; <span>/* void */</span> ; i++) {
  79. <span>if</span> (i >= part->nelts) {
  80. <span>if</span> (part->next == NULL) {
  81. <span>break</span>;
  82. }
  83. part = part->next;
  84. shm_zone = part->elts;
  85. i = <span>0</span>;
  86. }
  87. <span>if</span> (name->len != shm_zone[i].shm.name.len) {
  88. <span>continue</span>;
  89. }
  90. <span>if</span> (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len)
  91. != <span>0</span>)
  92. {
  93. <span>continue</span>;
  94. }
  95. <span>if</span> (tag != shm_zone[i].tag) {
  96. ngx_conf_log_error(NGX_LOG_EMERG, cf, <span>0</span>,
  97. <span>"the shared memory zone \"%V\" is "</span><span>"already declared for a different use"</span>,
  98. &shm_zone[i].shm.name);
  99. <span>return</span> NULL;
  100. }
  101. <span>if</span> (size && size != shm_zone[i].shm.size) {
  102. ngx_conf_log_error(NGX_LOG_EMERG, cf, <span>0</span>,
  103. <span>"the size %uz of shared memory zone \"%V\" "</span><span>"conflicts with already declared size %uz"</span>,
  104. size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
  105. <span>return</span> NULL;
  106. }
  107. <span>return</span> &shm_zone[i];
  108. }
  109. shm_zone = ngx_list_push(&cf->cycle->shared_memory);
  110. <span>if</span> (shm_zone == NULL) {
  111. <span>return</span> NULL;
  112. }
  113. shm_zone->data = NULL;
  114. shm_zone->shm.<span>log</span> = cf->cycle-><span>log</span>;
  115. shm_zone->shm.size = size;
  116. shm_zone->shm.name = *name;
  117. shm_zone->shm.exists = <span>0</span>;
  118. shm_zone->init = NULL;
  119. shm_zone->tag = tag;
  120. <span>return</span> shm_zone;
  121. }</code>

最后,推荐两本书:
《深入剖析Nginx》 by 高群凯
《深入理解Nginx ——模块开发与架构解析》 by 陶辉

').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('
  • ').text(i)); }; $numbering.fadeIn(1700); }); });

    以上就介绍了Nginx源码分析(1)之——共享内存的配置、分配及初始化,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

  • 人气教程排行