几个相关的数据类型
typedef struct { ngx_str_t name; void *(*create_conf)(ngx_cycle_t *cycle); char *(*init_conf)(ngx_cycle_t *cycle, void *conf); } ngx_core_module_t;
static ngx_core_module_t ngx_events_module_ctx = { ngx_string("events"), NULL, ngx_event_init_conf };
struct ngx_command_s { 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; }; #define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL }
static ngx_command_t ngx_events_commands[] = { { ngx_string("events"), NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_events_block, 0, 0, NULL }, ngx_null_command };
#define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 #define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0 struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; ngx_uint_t spare0; ngx_uint_t spare1; ngx_uint_t spare2; ngx_uint_t spare3; ngx_uint_t version; void *ctx; ngx_command_t *commands; ngx_uint_t type; ngx_int_t (*init_master)(ngx_log_t *log); ngx_int_t (*init_module)(ngx_cycle_t *cycle); ngx_int_t (*init_process)(ngx_cycle_t *cycle); ngx_int_t (*init_thread)(ngx_cycle_t *cycle); void (*exit_thread)(ngx_cycle_t *cycle); void (*exit_process)(ngx_cycle_t *cycle); void (*exit_master)(ngx_cycle_t *cycle); uintptr_t spare_hook0; uintptr_t spare_hook1; uintptr_t spare_hook2; uintptr_t spare_hook3; uintptr_t spare_hook4; uintptr_t spare_hook5; uintptr_t spare_hook6; uintptr_t spare_hook7; };
ngx_module_t *ngx_modules[] = { ... ... &ngx_events_module, &ngx_event_core_module, &ngx_epoll_module, ... }
ngx_module_t ngx_events_module = { NGX_MODULE_V1, &ngx_events_module_ctx, /* module context */ ngx_events_commands, /* module directives */ NGX_CORE_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_module_t ngx_event_core_module = { NGX_MODULE_V1, &ngx_event_core_module_ctx, /* module context */ ngx_event_core_commands, /* module directives */ NGX_EVENT_MODULE, /* module type */ NULL, /* init master */ ngx_event_module_init, /* init module */ ngx_event_process_init, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING };
ngx_module_t ngx_epoll_module = { NGX_MODULE_V1, ngx_epoll_module_ctx, /* module context */ ngx_epoll_commands, /* module directives */ NGX_EVENT_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_event_module_t ngx_epoll_module_ctx = { &epoll_name, ngx_epoll_create_conf, /* create configuration */ ngx_epoll_init_conf, /* init configuration */ { ngx_epoll_add_event, /* add an event */ ngx_epoll_del_event, /* delete an event */ ngx_epoll_add_event, /* enable an event */ ngx_epoll_del_event, /* disable an event */ ngx_epoll_add_connection, /* add an connection */ ngx_epoll_del_connection, /* delete an connection */ #if (NGX_HAVE_EVENTFD) ngx_epoll_notify, /* trigger a notify */ #else NULL, /* trigger a notify */ #endif ngx_epoll_process_events, /* process the events */ ngx_epoll_init, /* init the events */ ngx_epoll_done, /* done the events */ } };
static void * ngx_epoll_create_conf(ngx_cycle_t *cycle) { ngx_epoll_conf_t *epcf; epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t)); if (epcf == NULL) { return NULL; } epcf->events = NGX_CONF_UNSET; epcf->aio_requests = NGX_CONF_UNSET; return epcf; } static char * ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_epoll_conf_t *epcf = conf; ngx_conf_init_uint_value(epcf->events, 512); ngx_conf_init_uint_value(epcf->aio_requests, 32); return NGX_CONF_OK; }
1. 解析nginx配置文件nginx.conf中的event block,如:
events { use epoll; worker_connections 1024; }
当解析到events这个关键字时,会回调ngx_events_commands中的设置函数ngx_events_block
static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void ***ctx; ngx_uint_t i; ngx_conf_t pcf; ngx_event_module_t *m; if (*(void **) conf) { return "is duplicate"; } /* count the number of the event modules and set up their indices */ /*统计模块类型为event模块的数量,并记录,ctx_index就是用来记录每个模块内部所属的计数值, 总共有四种模块类型:1.core模块;2.http模块;3.event模块 4.mail模块*/ ngx_event_max_module = 0; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } ngx_modules[i]->ctx_index = ngx_event_max_module++; } /*申请一个指针*/ ctx = ngx_pcalloc(cf->pool, sizeof(void *)); if (ctx == NULL) { return NGX_CONF_ERROR; } /*指针内容也是一个指针内存数据*/ *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)); if (*ctx == NULL) { return NGX_CONF_ERROR; } /*返回值conf,将配置信息存在conf中*/ *(void **) conf = ctx; for (i = 0; ngx_modules[i]; i++) { /*跳过非NGX_EVENT_MODULE类型的模块*/ if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } /*目前只有两个类型为NGX_EVENT_MODULE的模块 1. ngx_event_core_module ----- 对应的ctx为ngx_event_core_module_ctx 2. ngx_epoll_module ---- 对应的ctx为ngx_epoll_module_ctx */ m = ngx_modules[i]->ctx; /*如果event模块的create_conf钩子函数不为空,则为该模块创建配置内存数据,如ngx_epoll_create_conf*/ if (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle); if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } /*cf指针就是指向配置文件的原始数据*/ pcf = *cf; cf->ctx = ctx; //这里的cf->ctx被赋值成了一个新分配的数组配置文件 cf->module_type = NGX_EVENT_MODULE; cf->cmd_type = NGX_EVENT_CONF; /*events是一个block指令,下面还有其他的配置项,如 use epoll,worker_connections 调用ngx_conf_parse函数解析子配置项*/ rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) return rv; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; /*如果event模块的init_conf钩子函数不为空,则为该模块初始化配置内存数据,如ngx_epoll_init_conf*/ if (m->init_conf) { rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]); if (rv != NGX_CONF_OK) { return rv; } } } return NGX_CONF_OK; }
当创建了一个worker进程ngx_worker_process_cycle后,worker进程首先就会做进程的初始化工作ngx_worker_process_init,此时会调用ngx_event_process_init函数。
static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) { ngx_uint_t m, i; ngx_event_t *rev, *wev; ngx_listening_t *ls; ngx_connection_t *c, *next, *old; ngx_core_conf_t *ccf; ngx_event_conf_t *ecf; ngx_event_module_t *module; /*获取core模块和event模块的配置信息*/ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); /*master进程打开,worker进程大于1,已经创建了accept_mutex 才打开accept互斥体*/ if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) { ngx_use_accept_mutex = 1; //使用互斥体 ngx_accept_mutex_held = 0; //是否获得accept互斥体 ngx_accept_mutex_delay = ecf->accept_mutex_delay; //争抢互斥体失败后,等待下次争抢时间间 } else { ngx_use_accept_mutex = 0; } #if (NGX_WIN32) /* * disable accept mutex on win32 as it may cause deadlock if * grabbed by a process which can't accept connections */ ngx_use_accept_mutex = 0; #endif ngx_queue_init(&ngx_posted_accept_events); ngx_queue_init(&ngx_posted_events); //初始化计数器,此处将会创建一颗红黑树,来维护计时器, if (ngx_event_timer_init(cycle->log) == NGX_ERROR) { return NGX_ERROR; } for (m = 0; ngx_modules[m]; m++) { /*循环模块,跳过模块类型为非NGX_EVENT_MODULE类型的模块*/ if (ngx_modules[m]->type != NGX_EVENT_MODULE) { continue; } /*不是use配置指令指定的模块跳过,默认是epoll,即如果在event block中使用了use epoll,才会走下去*/ if (ngx_modules[m]->ctx_index != ecf->use) { continue; } module = ngx_modules[m]->ctx; /*这里的module为epoll模块,init函数就是ngx_epoll_init*/ if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) { /* fatal */ exit(2); } break; } #if !(NGX_WIN32) if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) { struct sigaction sa; struct itimerval itv; ngx_memzero(&sa, sizeof(struct sigaction)); sa.sa_handler = ngx_timer_signal_handler; sigemptyset(&sa.sa_mask); if (sigaction(SIGALRM, &sa, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigaction(SIGALRM) failed"); return NGX_ERROR; } itv.it_interval.tv_sec = ngx_timer_resolution / 1000; itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000; itv.it_value.tv_sec = ngx_timer_resolution / 1000; itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } if (ngx_event_flags & NGX_USE_FD_EVENT) { struct rlimit rlmt; if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "getrlimit(RLIMIT_NOFILE) failed"); return NGX_ERROR; } cycle->files_n = (ngx_uint_t) rlmt.rlim_cur; cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n, cycle->log); if (cycle->files == NULL) { return NGX_ERROR; } } #endif /*创建全局的ngx_connection_t数组,保存所有的connection 由于这个过程是在各个worker进程中执行的,所以每个worker都有自己的connection数组*/ cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log); if (cycle->connections == NULL) { return NGX_ERROR; } c = cycle->connections; //创建一个读事件数组 cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n, cycle->log); if (cycle->read_events == NULL) { return NGX_ERROR; } rev = cycle->read_events; for (i = 0; i < cycle->connection_n; i++) { rev[i].closed = 1; rev[i].instance = 1; } //创建一个写事件数组 cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n, cycle->log); if (cycle->write_events == NULL) { return NGX_ERROR; } wev = cycle->write_events; for (i = 0; i < cycle->connection_n; i++) { wev[i].closed = 1; } i = cycle->connection_n; next = NULL; //初始化整个connection数组 do { i--; c[i].data = next; c[i].read = &cycle->read_events[i]; c[i].write = &cycle->write_events[i]; c[i].fd = (ngx_socket_t) -1; next = &c[i]; } while (i); /*初始化完成后,free_connections指向connection数组的第一个*/ cycle->free_connections = next; /*初始化后,空闲的连接数等于配置的连接数*/ cycle->free_connection_n = cycle->connection_n; /* for each listening socket */ ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { /*从connection数组中取得一个空闲的位置slot*/ c = ngx_get_connection(ls[i].fd, cycle->log); if (c == NULL) { return NGX_ERROR; } c->log = &ls[i].log; c->listening = &ls[i]; ls[i].connection = c; rev = c->read; rev->log = c->log; rev->accept = 1; //读时间发生,调用accept #if (NGX_HAVE_DEFERRED_ACCEPT) rev->deferred_accept = ls[i].deferred_accept; #endif if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) { if (ls[i].previous) { /* * delete the old accept events that were bound to * the old cycle read events array */ old = ls[i].previous->connection; if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) { return NGX_ERROR; } old->fd = (ngx_socket_t) -1; } } #if (NGX_WIN32) if (ngx_event_flags & NGX_USE_IOCP_EVENT) { ngx_iocp_conf_t *iocpcf; rev->handler = ngx_event_acceptex; if (ngx_use_accept_mutex) { continue; } if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) { return NGX_ERROR; } ls[i].log.handler = ngx_acceptex_log_error; iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module); if (ngx_event_post_acceptex(&ls[i], iocpcf->post_acceptex) == NGX_ERROR) { return NGX_ERROR; } } else { rev->handler = ngx_event_accept; if (ngx_use_accept_mutex) { continue; } if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } } #else /*注册套接字读事件的回调函数*/ rev->handler = ngx_event_accept; //使用了accept_mutex,暂时不将监听套接字放入epoll中,而是 //等到worker抢到accept互斥体后,再放入epoll,避免惊群的发生 if (ngx_use_accept_mutex) { continue; } if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (ngx_add_conn(c) == NGX_ERROR) { return NGX_ERROR; } } else { //没有使用accept互斥体,那么就将此监听套接字放入epoll中。 if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } } #endif } return NGX_OK; }