> 백엔드 개발 > PHP 튜토리얼 > Nginx 소스 코드 분석(1) - 공유 메모리 구성, 할당 및 초기화

Nginx 소스 코드 분석(1) - 공유 메모리 구성, 할당 및 초기화

WBOY
풀어 주다: 2016-07-29 08:57:12
원래의
1261명이 탐색했습니다.

Nginx에서는 완전한 공유 메모리가 캡슐화되어 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>
로그인 후 복사

Nginx에서 공유 메모리를 사용하려면 공유 메모리의 이름, 크기 등 공유 메모리 관련 정보(명령어 추가)를 구성 파일에 추가해야 합니다. 공유 메모리 등 따라서 구성 파싱(configuration parsing) 단계에서 해당 명령어를 파싱하면 해당 공유 메모리가 생성된다(이때 공유 메모리를 나타내는 구조체인 ngx_shm_zone_t만 생성된다. 실제 공유 메모리는 ngx_init_cycle(&init_cycle) 이후에 할당된다. 실제 공유 메모리를 할당하고 초기화합니다. 참조:

<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>
로그인 후 복사

마지막으로 두 권의 책을 추천합니다:
Gao Qunkai의 "Nginx 심층 분석"
"Nginx에 대한 심층적인 이해 - 모듈 개발 및 아키텍처 분석" by Tao Hui

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

위 내용은 Nginx 소스 코드 분석(1) - 공유 메모리의 구성, 할당 및 초기화 내용을 포함하여 PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿