您好,登錄后才能下訂單哦!
這篇文章主要介紹“nginx啟動初始化代碼執行流程是什么”,在日常操作中,相信很多人在nginx啟動初始化代碼執行流程是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”nginx啟動初始化代碼執行流程是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
ngx_event_process_init:遍歷connections,初始化listenfd的回調函數,添加事件監聽
static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) { ... cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log); cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n, cycle->log); ... ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ngx_get_connection(ls[i].fd, cycle->log); c->listening = &ls[i]; rev = c->read; } ... rev->handler = ngx_event_accept; ngx_add_event(rev, NGX_READ_EVENT, 0) ... } |
ngx_event_accept:調用ngx_listening_t的回調函數
void ngx_event_accept(ngx_event_t *ev) { ... lc = ev->data; ls = lc->listening; ... s = accept(lc->fd, (struct sockaddr *) sa, &socklen); c = ngx_get_connection(s, ev->log); ngx_add_conn(c) ls->handler(c); ... } |
找到ls->handler(c)的位置
static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ... if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) { return NGX_CONF_ERROR; } ... } static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports) { ... if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) { return NGX_ERROR; } ... } static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port) { ... ls = ngx_http_add_listening(cf, &addr[i]); if (ls == NULL) { return NGX_ERROR; } ... } static ngx_listening_t * ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) { ... ls->handler = ngx_http_init_connection; ... } |
第三方模塊(輸出):
server { listen 0.0.0.0:70; location / { root /usr/local/nginx/html/bak/; limit_req zone=req10k burst=5 nodelay; shuchu "helloworld"; } } |
一個模塊的三大核心
static ngx_command_t ngx_http_shuchu_commands[] = { { ngx_string("shuchu"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_shuchu, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_shuchu_loc_conf_t, content), NULL, }, ngx_null_command, }; static ngx_http_module_t ngx_http_shuchu_ctx = { NULL, ngx_http_shuchu_init, NULL, NULL, NULL, NULL, ngx_http_shuchu_create_loc_conf, ngx_http_shuchu_merge_loc_conf }; ngx_module_t ngx_http_shuchu_module = { NGX_MODULE_V1, &ngx_http_shuchu_ctx, /* module context */ ngx_http_shuchu_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; |
ngx_conf_parse:解析配置
char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { ... type = parse_file; fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); rc = ngx_conf_read_token(cf); 省略對rc和type組合的判定 rc = ngx_conf_handler(cf, rc); ... } |
ngx_conf_handler:對指令進行處理
static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last) { ... for (i = 0; ngx_modules[i]; i++) { cmd = ngx_modules[i]->commands; for ( /* void */ ; cmd->name.len; cmd++) { if (cmd->type & NGX_DIRECT_CONF) { conf = ((void **) cf->ctx)[ngx_modules[i]->index]; } else if (cmd->type & NGX_MAIN_CONF) { conf = &(((void **) cf->ctx)[ngx_modules[i]->index]); } else if (cf->ctx) { confp = *(void **) ((char *) cf->ctx + cmd->conf); if (confp) { conf = confp[ngx_modules[i]->ctx_index]; } } rv = cmd->set(cf, cmd, conf); } } ... } |
ngx_http_block
static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ... ctx->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[m]->ctx; mi = ngx_modules[m]->ctx_index; if (module->create_main_conf) { ctx->main_conf[mi] = module->create_main_conf(cf); if (ctx->main_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_srv_conf) { ctx->srv_conf[mi] = module->create_srv_conf(cf); if (ctx->srv_conf[mi] == NULL) { return NGX_CONF_ERROR; } } if (module->create_loc_conf) { ctx->loc_conf[mi] = module->create_loc_conf(cf); if (ctx->loc_conf[mi] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; ... /* parse inside the http{} block */ cf->module_type = NGX_HTTP_MODULE; cf->cmd_type = NGX_HTTP_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); ... } |
ngx_http_core_server
static char * ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { ... ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } http_ctx = cf->ctx; ctx->main_conf = http_ctx->main_conf; ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); ... cscf = ctx->srv_conf[ngx_http_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_HTTP_SRV_CONF; rv = ngx_conf_parse(cf, NULL); ... } |
ngx_http_core_listen
static char * ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ... cscf->listen = 1; value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; ngx_parse_url(cf->pool, &u); if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) { return NGX_CONF_OK; } ... } |
ngx_http_add_listen
ngx_int_t ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_listen_opt_t *lsopt) { ... cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); if (cmcf->ports == NULL) { cmcf->ports = ngx_array_create(cf->temp_pool, 2, sizeof(ngx_http_conf_port_t)); if (cmcf->ports == NULL) { return NGX_ERROR; } } sin = &lsopt->u.sockaddr_in; p = sin->sin_port; port = ngx_array_push(cmcf->ports); port->family = sa->sa_family; port->port = p; port->addrs.elts = NULL; ngx_http_add_address(cf, cscf, port, lsopt); ... } |
ngx_http_add_address
static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) { ... addr = ngx_array_push(&port->addrs); addr->opt = *lsopt; addr->default_server = cscf; ...} |
ngx_http_add_server
static ngx_int_t ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr) { ... server = ngx_array_push(&addr->servers); *server = cscf; ... } |
到這里為止,整個配置的基本架構已經搞起來了,port(ngx_http_conf_port_t)下掛著多個監聽的地址(ngx_http_conf_addr_t),每個地址后的opt目前都是配置里面讀出來,存著監聽器的信息,監聽地址(ngx_http_conf_addr_t)后面還掛著這個監聽地址所存在的server塊(ngx_http_core_srv_conf_t),接下來就要最后在optmize一下,把opt里的東西搞一下,然后做hash:
ngx_http_optimize_servers
static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports) { ... port = ports->elts; for (p = 0; p < ports->nelts; p++) { addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) { return NGX_ERROR; } } if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) { return NGX_ERROR; } } ... } |
ngx_http_server_names:整理addr中的servers,將sn和對應的srv_conf對應起來
static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports) { ... ha.pool = cf->pool; cscfp = addr->servers.elts; for (s = 0; s < addr->servers.nelts; s++) { name = cscfp[s]->server_names.elts; for (n = 0; n < cscfp[s]->server_names.nelts; n++) { rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, NGX_HASH_WILDCARD_KEY); } ... hash.hash = &addr->hash; ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts); } ... } |
ngx_http_add_listening
static ngx_listening_t * ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) { ... ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen); ls->handler = ngx_http_init_connection; ... } |
instance
每次get_connection都會將instance取反,s是accept獲取的socket,是一個int,賦值給c->fd
ngx_connection_t * ngx_get_connection(ngx_socket_t s, ngx_log_t *log) { ... c = ngx_cycle->free_connections; ngx_cycle->free_connections = c->data; ngx_cycle->free_connection_n--; rev = c->read; wev = c->write; ngx_memzero(c, sizeof(ngx_connection_t)); c->read = rev; c->write = wev; c->fd = s; rev->instance = !instance; wev->instance = !instance; rev->data = c; wev->data = c; return c; ... } |
而free的時候只移動鏈表,清空文件,將當前鏈表變成可用
void ngx_free_connection(ngx_connection_t *c) { ... c->data = ngx_cycle->free_connections; ngx_cycle->free_connections = c; ngx_cycle->free_connection_n++; if (ngx_cycle->files) { ngx_cycle->files[c->fd] = NULL; ... } |
而無論是add_event還是add_connection,都是直接將epoll指向的直接與instance,在process_events的時候,拿出來事件指向的
static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) { ... ee.data.ptr = (void *) ((uintptr_t) c | ev->instance); ... } |
static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { ... c = event_list[i].data.ptr; instance = (uintptr_t) c & 1; if (c->fd == -1 || rev->instance != instance) { ... } |
到此,關于“nginx啟動初始化代碼執行流程是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。