Nginx的高性能应该算是事件驱动的功劳。Nginx事件处理的相关代码位于src/event目录中,事件驱动是Nginx的核心,所以代码量相对也比较大。事件驱动初始化的过程主要由下图中的三步组成。
第一步:解析配置文件的初始化
在Nginx的启动初始化过程中,将调用ngx_conf_parse()解析配置文件,此过程将遇到类似如下的配置项:
events {
worker_connections 20480;
}
此处的events是一个block指令,在它下面还可以配置很多其他的指令,比如这里的worker_connections等。events下面可以配置的指令定义在数组ngx_event_core_commands(位于src/event/ngx_event.c文件中)中。每个指令都有自己对应的回调函数,events指令的回调函数是ngx_events_block()(位于src/events/ngx_event.c文件中),即在解析配置文件到events指令的时候,将调用此回调函数。此函数的大概分析如下:
- 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;
-
-
- 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;
- }
- *(void **) conf = ctx;
-
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
- continue;
- }
- m = ngx_modules[i]->ctx;
- 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;
- }
- }
- }
- pcf = *cf;
- cf->ctx = ctx;
- cf->module_type = NGX_EVENT_MODULE;
- cf->cmd_type = NGX_EVENT_CONF;
-
-
- 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;
- 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;
- }
- static ngx_int_t
- ngx_event_module_init(ngx_cycle_t *cycle)
- {
- void ***cf;
- u_char *shared;
- size_t size, cl;
- ngx_shm_t shm;
- ngx_time_t *tp;
- ngx_core_conf_t *ccf;
- ngx_event_conf_t *ecf;
-
- cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);
- if (cf == NULL) {
- return NGX_ERROR;
- }
-
- ecf = (*cf)[ngx_event_core_module.ctx_index];
-
- ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
-
- ngx_timer_resolution = ccf->timer_resolution;
- 。。。。。。。。。。。。。。。。。。。。
-
-
-
- if (ccf->master == 0) {
- return NGX_OK;
- }
-
- if (ngx_accept_mutex_ptr) {
- return NGX_OK;
- }
-
- cl = 128;
-
-
-
-
- size = cl
- + cl
- + cl;
- 。。。。。。。。。。。。。。。。。。。。。
-
- shm.size = size;
- shm.name.len = sizeof("nginx_shared_zone");
- shm.name.data = (u_char *) "nginx_shared_zone";
- shm.log = cycle->log;
-
- if (ngx_shm_alloc(&shm) != NGX_OK) {
- return NGX_ERROR;
- }
-
- shared = shm.addr;
-
-
- ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
-
-
-
-
-
-
-
-
-
- if (ngx_shmtx_create(&ngx_accept_mutex, shared, cycle->lock_file.data)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
- (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
-
-
- ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
- 。。。。。。。。。。。。。。。。。。。。。。
- return NGX_OK;
- }
第三步:ngx_event_process_init
在worker进程的分析中,有提到调用每个模块自定义的进程初始化函数。ngx_event_process_init回调函数就是ngx_event_core_commands模块自定义的进程初始化函数。因此,在master进程创建好了一个worker进程后,worker进程首先就会做进程的初始化工作,此时就会调用ngx_event_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;
-
- 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);
-
-
-
- if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
- ngx_use_accept_mutex = 1;
- ngx_accept_mutex_held = 0;
- ngx_accept_mutex_delay = ecf->accept_mutex_delay;
- } else {
- ngx_use_accept_mutex = 0;
- }
-
- if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
- return NGX_ERROR;
- }
- for (m = 0; ngx_modules[m]; m++) {
- if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
- continue;
- }
- if (ngx_modules[m]->ctx_index != ecf->use) {
- continue;
- }
- module = ngx_modules[m]->ctx;
-
-
-
-
-
-
-
-
-
-
-
- if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
-
- exit(2);
- }
- break;
- }
- 。。。。。。。。。。。。。。。。。。。。。。。。。
-
-
-
-
- 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;
-
-
-
-
-
- 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);
- cycle->free_connections = next;
- cycle->free_connection_n = cycle->connection_n;
-
-
-
- ls = cycle->listening.elts;
- for (i = 0; i < cycle->listening.nelts; i++) {
-
- 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;
- 。。。。。。。。。。。。。。。。。。。。
- #if (NGX_WIN32)
- 。。。。。。。。。。。。。。。。。。。
- #else
-
- rev->handler = ngx_event_accept;
-
-
-
-
- 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 {
-
-
-
- if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
- #endif
- }
- return NGX_OK;
- }
至此,事件驱动的初始化三步曲就分析完了。
本文摘自:http://blog.csdn.net/marcky/article/details/6025647感谢作者
阅读(1932) | 评论(0) | 转发(0) |