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,? ngx_http_shuchu_commands,? NGX_HTTP_MODULE, NULL,? NULL,? NULL,? NULL,? NULL,? NULL,? NULL,? 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_RDON *** , 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 ( ; 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; ... 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; 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) { ... } |
本文目录一览: 1、黑客是怎样练成的? 2、如何创建一个符合黑客条件的系统?? 3、黑客会开发软件吗 黑客是怎样练成的? 最经典的黑客技术入门知识以我的理解,“黑客”大体上应该分为“正”、“...
长春市高档商务私人伴游预约【皮静娴】,上海市是一座成功者的集中地,对商业服务女学妹的要求也是较为大的,今日大牌明星商务共享女学妹访梦,年纪杭州市 男 43,婚姻生活:己婚,文凭:大学本科,气场:长春市...
因为2020年独特恶性事件的危害,无论是中国還是海外,都让许多 知名品牌遭受了重挫。美国一直拥有 近百年历史时间、在全世界有着超出1200家店面和特许加盟店的鞋品知名品牌Clarks就“逃不过一劫”。...
如今,有很多用户使用微信进行社交聊天。大多数合作伙伴喜欢微信聊天,寄红包,增进友谊和家庭。最近,一些用户想查询发送和接收红包的记录。所以小编在这里分享微信查询红包记录的过程。我们一起来看看。 在...
此刻咖啡行业的成长长短常不错的,不知道你是否传闻过costa咖啡加盟项目,该品牌在市场上成长多年,品牌形象已经深入人心,深受宽大消费者的喜爱与追捧,选择加盟长短常不错的一个选择,那么costa咖啡如何...
楼主.很认真的跟你说.你仔细看看它们发的网站.都是收费的!邀请码什么的.咱们都是为了学习技术.不要成了它们赚钱的机器!我推荐给你一个免费的.技术。 QQ被盗了,只要在登陆处点击那个忘记密码。会出现申诉...