Nginx源碼分析(1)之——共用記憶體的配置、分配及初始化

來源:互聯網
上載者:User
在Nginx裡,一塊完整的共用記憶體以資料結構ngx_shm_zone_t來封裝表示。

typedefstruct {    u_char      *addr;     // 分配的共用記憶體的實際地址(這裡實際共用記憶體的分配,根據當前系統可提供的介面,可以調用mmap或者shmget來進行分配,具體的用法,自己man吧)    size_t       size;     // 共用記憶體的大小    ngx_str_t    name;     // 該欄位用作共用記憶體的唯一標識,能讓Nginx知道想使用哪個共用記憶體    ngx_log_t   *log;    ngx_uint_t   exists;   /* unsigned  exists:1;  */} ngx_shm_t;typedefstruct ngx_shm_zone_s  ngx_shm_zone_t;typedef ngx_int_t (*ngx_shm_zone_init_pt) (ngx_shm_zone_t *zone, void *data);struct ngx_shm_zone_s {    void                     *data;    ngx_shm_t                 shm;    ngx_shm_zone_init_pt      init; // 這裡有一個鉤子函數,用於實際共用記憶體進行分配後的初始化void                     *tag;  // 區別於shm.name,shm.name沒法讓Nginx區分到底是想新建立一個共用記憶體,還是使用已存在的舊的共用記憶體// 因此這裡引入tag欄位來解決該問題,tag一般指向當前模組的ngx_module_t變數,見:...};

要在Nginx裡使用一個共用記憶體,需要在設定檔裡加上該共用記憶體的相關資訊(添加一條指令),如:共用記憶體的名稱,共用記憶體的大小等。因此在配置解析階段,解析到相應的指令時,會建立對應的共用記憶體(此時建立的僅僅是代表共用記憶體的結構體:ngx_shm_zone_t,真實共用記憶體的分配在ngx_init_cycle(&init_cycle)解析完配置後,進行實際共用記憶體的分配並初始化)。見:

int ngx_cdeclmain(int argc, char *const *argv) // 在master進程中{    cycle = ngx_init_cycle(&init_cycle);    {        if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { // 解析配置        {            解析到http指令(進入ngx_http_block())            {                // 會依次執行typedefstruct {                    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);                        /* 執行順序4 */                    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);                       /* 執行順序8 */void       *(*create_main_conf)(ngx_conf_t *cf);                        /* 執行順序1 */char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);              /* 執行順序5 */void       *(*create_srv_conf)(ngx_conf_t *cf);                         /* 執行順序2 */char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);  /* 執行順序6 */void       *(*create_loc_conf)(ngx_conf_t *cf);                         /* 執行順序3 */char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);  /* 執行順序7 */                } ngx_http_module_t;                同時,還有個執行順序4.5:                struct ngx_command_s {                                                      /* 執行順序4.5 */                    ngx_str_t             name;                    ngx_uint_t            type;                    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);                    ngx_uint_t            conf;                    ngx_uint_t            offset;                    void                 *post;                };                for (m = 0; ngx_modules[m]; m++) {                    if (module->create_main_conf) {ctx->main_conf[mi] = module->create_main_conf(cf);}                    if (module->create_srv_conf) {ctx->srv_conf[mi] = module->create_srv_conf(cf);}                    if (module->create_loc_conf) {ctx->loc_conf[mi] = module->create_loc_conf(cf);}                }                for (m = 0; ngx_modules[m]; m++) {                    if (module->preconfiguration) {if (module->preconfiguration(cf) != NGX_OK) {}                }                rv = ngx_conf_parse(cf, NULL);                {                    /*                     * 指令的解析                     * 共用記憶體配置相關的指令也在這裡進行解析                     * 詳細見:                     * ngx_shm_zone_t *                     * ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)                     */                }                for (m = 0; ngx_modules[m]; m++) {                    if (module->init_main_conf) {rv = module->init_main_conf(cf, ctx->main_conf[mi]);}                    rv = ngx_http_merge_servers(cf, cmcf, module, mi);                }                for (m = 0; ngx_modules[m]; m++) {                    if (module->postconfiguration) {if (module->postconfiguration(cf) != NGX_OK)}                }            }        }        // in ngx_init_cycle(&init_cycle)        line: 462if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK)           /* 實際共用記憶體配置的地方 */        line: 466if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK)        /* 共用記憶體管理機制的初始化         * 共用記憶體的使用涉及另外兩個主題:         * 1、多進程共同使用時之間的互斥問題         * 2、引入特定的使用方式(slab機制,這在下一個主題:“Nginx源碼分析(2)之——共用記憶體管理之slab機制”中進行介紹),以提高效能         */        line: 470if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK)      /* 分配之後的初始化 */    }}ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag){    ngx_uint_t        i;    ngx_shm_zone_t   *shm_zone;    ngx_list_part_t  *part;    /*     * 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指向的真實共用記憶體並沒有進行實際的分配     */    part = &cf->cycle->shared_memory.part;    shm_zone = part->elts;    for (i = 0; /* void */ ; i++) {        if (i >= part->nelts) {            if (part->next == NULL) {                break;            }            part = part->next;            shm_zone = part->elts;            i = 0;        }        if (name->len != shm_zone[i].shm.name.len) {            continue;        }        if (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len)            != 0)        {            continue;        }        if (tag != shm_zone[i].tag) {            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                            "the shared memory zone \"%V\" is ""already declared for a different use",                            &shm_zone[i].shm.name);            return NULL;        }        if (size && size != shm_zone[i].shm.size) {            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                            "the size %uz of shared memory zone \"%V\" ""conflicts with already declared size %uz",                            size, &shm_zone[i].shm.name, shm_zone[i].shm.size);            return NULL;        }        return &shm_zone[i];    }    shm_zone = ngx_list_push(&cf->cycle->shared_memory);    if (shm_zone == NULL) {        return NULL;    }    shm_zone->data = NULL;    shm_zone->shm.log = cf->cycle->log;    shm_zone->shm.size = size;    shm_zone->shm.name = *name;    shm_zone->shm.exists = 0;    shm_zone->init = NULL;    shm_zone->tag = tag;    return shm_zone;}

最後,推薦兩本書:
《深入剖析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教程有興趣的朋友有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.