Home > Backend Development > PHP Tutorial > Nginx source code analysis (1) - configuration, allocation and initialization of shared memory

Nginx source code analysis (1) - configuration, allocation and initialization of shared memory

WBOY
Release: 2016-07-29 08:57:12
Original
1260 people have browsed it

In Nginx, a complete shared memory is encapsulated and represented by the data structure ngx_shm_zone_t.

<code><span>typedef</span><span>struct</span> {
    u_char      *addr;     <span>// 分配的共享内存的实际地址(这里实际共享内存的分配,根据当前系统可提供的接口,可以调用mmap或者shmget来进行分配,具体的用法,自己man吧)</span>
    size_t       size;     <span>// 共享内存的大小</span>
    ngx_str_t    name;     <span>// 该字段用作共享内存的唯一标识,能让Nginx知道想使用哪个共享内存</span>
    ngx_log_t   *<span>log</span>;
    ngx_uint_t   exists;   <span>/* unsigned  exists:1;  */</span>
} ngx_shm_t;

<span>typedef</span><span>struct</span> ngx_shm_zone_s  ngx_shm_zone_t;

<span>typedef</span> ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, <span>void</span> *data);

<span>struct</span> ngx_shm_zone_s {
    <span>void</span>                     *data;
    ngx_shm_t                 shm;
    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>
};</code>
Copy after login

To use a shared memory in Nginx, you need to add the relevant information of the shared memory in the configuration file (add an instruction), such as: the name of the shared memory, the size of the shared memory, etc. Therefore, in the configuration parsing phase, when the corresponding instruction is parsed, the corresponding shared memory will be created (at this time, only the structure representing the shared memory is created: ngx_shm_zone_t. The real shared memory is allocated after ngx_init_cycle(&init_cycle) parses the configuration. Allocate and initialize actual shared memory). See:

<code><span>int</span> ngx_cdecl
main(<span>int</span> argc, <span>char</span> *<span>const</span> *argv) <span>// 在master进程中</span>
{
    cycle = ngx_init_cycle(&init_cycle);
    {
        <span>if</span> (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { <span>// 解析配置</span>
        {
            解析到http指令(进入ngx_http_block())
            {
                <span>// 会依次执行</span><span>typedef</span><span>struct</span> {
                    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);                        <span>/* 执行顺序4 */</span>
                    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>
                } ngx_http_module_t;
                同时,还有个执行顺序<span>4.5</span>:
                <span>struct</span> ngx_command_s {                                                      <span>/* 执行顺序4.5 */</span>
                    ngx_str_t             name;
                    ngx_uint_t            type;
                    <span>char</span>               *(*<span>set</span>)(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf);
                    ngx_uint_t            conf;
                    ngx_uint_t            offset;
                    <span>void</span>                 *post;
                };


                <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
                    <span>if</span> (module->create_main_conf) {ctx->main_conf[mi] = module->create_main_conf(cf);}
                    <span>if</span> (module->create_srv_conf) {ctx->srv_conf[mi] = module->create_srv_conf(cf);}
                    <span>if</span> (module->create_loc_conf) {ctx->loc_conf[mi] = module->create_loc_conf(cf);}
                }
                <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
                    <span>if</span> (module->preconfiguration) {<span>if</span> (module->preconfiguration(cf) != NGX_OK) {}
                }

                rv = ngx_conf_parse(cf, NULL);
                {
                    <span>/*
                     * 指令的解析
                     * 共享内存配置相关的指令也在这里进行解析
                     * 详细见:
                     * ngx_shm_zone_t *
                     * ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)
                     */</span>                }

                <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
                    <span>if</span> (module->init_main_conf) {rv = module->init_main_conf(cf, ctx->main_conf[mi]);}
                    rv = ngx_http_merge_servers(cf, cmcf, module, mi);
                }
                <span>for</span> (m = <span>0</span>; ngx_modules[m]; m++) {
                    <span>if</span> (module->postconfiguration) {<span>if</span> (module->postconfiguration(cf) != NGX_OK)}
                }
            }
        }

        <span>// in ngx_init_cycle(&init_cycle)</span>
        line: <span>462</span><span>if</span> (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK)           <span>/* 实际共享内存分配的地方 */</span>
        line: <span>466</span><span>if</span> (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK)
        <span>/* 共享内存管理机制的初始化
         * 共享内存的使用涉及另外两个主题:
         * 1、多进程共同使用时之间的互斥问题
         * 2、引入特定的使用方式(slab机制,这在下一个主题:“Nginx源码分析(2)之——共享内存管理之slab机制”中进行介绍),以提高性能
         */</span>
        line: <span>470</span><span>if</span> (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK)      <span>/* 分配之后的初始化 */</span>
    }
}

ngx_shm_zone_t *
ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, <span>void</span> *tag)
{
    ngx_uint_t        i;
    ngx_shm_zone_t   *shm_zone;
    ngx_list_part_t  *part;

    <span>/*
     * Nginx中所有的共享内存都以list链表的形式组织在全局变量cf->cycle->shared_memory中
     * 在创建新的共享内存之前,会对该链表进行遍历查找以及冲突检测,
     * 对于已经存在且不存在冲突时,对共享内存直接进行返回并引用
     * 存在且不存在冲突:共享内存的名称相同,大小相同,且tag指向的是同一个模块
     * 有冲突,则报错
     * 否则,重新分配ngx_shm_zone_t,并挂到全局链表cf->cycle->shared_memory中,最后进行结构初始化
     * shm_zone = ngx_list_push(&cf->cycle->shared_memory);
     * 至此:
     * 仅仅是创建了共享内存的结构体:ngx_shm_zone_t,ngx_shm_zone_t.shm.addr指向的真实共享内存并没有进行实际的分配
     */</span>
    part = &cf->cycle->shared_memory.part;
    shm_zone = part->elts;

    <span>for</span> (i = <span>0</span>; <span>/* void */</span> ; i++) {

        <span>if</span> (i >= part->nelts) {
            <span>if</span> (part->next == NULL) {
                <span>break</span>;
            }
            part = part->next;
            shm_zone = part->elts;
            i = <span>0</span>;
        }

        <span>if</span> (name->len != shm_zone[i].shm.name.len) {
            <span>continue</span>;
        }

        <span>if</span> (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len)
            != <span>0</span>)
        {
            <span>continue</span>;
        }

        <span>if</span> (tag != shm_zone[i].tag) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, <span>0</span>,
                            <span>"the shared memory zone \"%V\" is "</span><span>"already declared for a different use"</span>,
                            &shm_zone[i].shm.name);
            <span>return</span> NULL;
        }

        <span>if</span> (size && size != shm_zone[i].shm.size) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, <span>0</span>,
                            <span>"the size %uz of shared memory zone \"%V\" "</span><span>"conflicts with already declared size %uz"</span>,
                            size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
            <span>return</span> NULL;
        }

        <span>return</span> &shm_zone[i];
    }

    shm_zone = ngx_list_push(&cf->cycle->shared_memory);

    <span>if</span> (shm_zone == NULL) {
        <span>return</span> NULL;
    }

    shm_zone->data = NULL;
    shm_zone->shm.<span>log</span> = cf->cycle-><span>log</span>;
    shm_zone->shm.size = size;
    shm_zone->shm.name = *name;
    shm_zone->shm.exists = <span>0</span>;
    shm_zone->init = NULL;
    shm_zone->tag = tag;

    <span>return</span> shm_zone;
}</code>
Copy after login

Finally, two books are recommended:
"In-depth Analysis of Nginx" by Gao Qunkai
"In-depth understanding of Nginx - module development and architecture analysis" by Tao Hui

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

The above introduces Nginx source code analysis (1) - the configuration, allocation and initialization of shared memory, including aspects of the content. I hope it will be helpful to friends who are interested in PHP tutorials.

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template