在nginx在启动过程,ngx_init_cycle这个函数最初始工作。变量的初始化存储在ngx_cycle_t这个结构体中,为了深入了解这个函数都做了那些初始化工作,就化时间研究了一下。并写下来以便以后參考。
1ngx_cycle_t
关于这个结构体前面已经简介过,这里不再赘述。
2ngx_init_cycle
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle);
先看一下这个old_cycle參数从哪里来的:
ngx_cycle_t *cycle, init_cycle; init_cycle.pool = ngx_create_pool(1024, log);//创建内存池 if (init_cycle.pool == NULL) { return 1; } ...... ...... if (ngx_process_options(&init_cycle) != NGX_OK) { return 1; } cycle = ngx_init_cycle(&init_cycle);
可见在调用ngx_int_cycle之前,这个old_cycle已经保存了一些參数。这些參数包含:prefix,conf_prefix,conf_file, conf_para。主要在ngx_process_options这个函数中初始化old_cycle。这个函数比較简单,看一下代码:
static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) { u_char *p; size_t len; if (ngx_prefix) { len = ngx_strlen(ngx_prefix); p = ngx_prefix; if (!ngx_path_separator(*p)) { p = ngx_pnalloc(cycle->pool, len + 1); if (p == NULL) { return NGX_ERROR; } ngx_memcpy(p, ngx_prefix, len); p[len++] = '/'; } cycle->conf_prefix.len = len; cycle->conf_prefix.data = p; cycle->prefix.len = len; cycle->prefix.data = p; } else { #ifndef NGX_PREFIX p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH); if (p == NULL) { return NGX_ERROR; } if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {//得到当前的工作文件夹 ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed"); return NGX_ERROR; } len = ngx_strlen(p); p[len++] = '/'; cycle->conf_prefix.len = len; cycle->conf_prefix.data = p;//配置文件夹 cycle->prefix.len = len; cycle->prefix.data = p;//安装文件夹 #else #ifdef NGX_CONF_PREFIX ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);//配置文件相对于安装的文件夹 #else ngx_str_set(&cycle->conf_prefix, NGX_PREFIX); #endif ngx_str_set(&cycle->prefix, NGX_PREFIX); #endif } if (ngx_conf_file) { cycle->conf_file.len = ngx_strlen(ngx_conf_file); cycle->conf_file.data = ngx_conf_file; } else { ngx_str_set(&cycle->conf_file, NGX_CONF_PATH); } if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) { return NGX_ERROR; } for (p = cycle->conf_file.data + cycle->conf_file.len - 1; p > cycle->conf_file.data; p--) { if (ngx_path_separator(*p)) { cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1; cycle->conf_prefix.data = ngx_cycle->conf_file.data; break; } } if (ngx_conf_params) { cycle->conf_param.len = ngx_strlen(ngx_conf_params); cycle->conf_param.data = ngx_conf_params; } if (ngx_test_config) { cycle->log->log_level = NGX_LOG_INFO; } return NGX_OK; }
如今開始进入关键:ngx_init_cycle,依照运行步骤来进行
2.1调用ngx_timezone_update()、ngx_timeofday() 、ngx_time_update(0,0)做时间校准
ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update();
2.2创建一个新的ngx_cycle_t变量cycle,而且初始化其大部分的成员字段。有一些是从传入的old_cycle直接拷贝过来的,这些字段包含:log,conf_prefix,prefix,conf_file,conf_param,初始化pathes数组、初始化open_files链表、初始化shared_memory链表、初始化listening数组等等。
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));//返回的新的cycle。以后这个cycle就是全局的 if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool;//全局cycle的内存池 cycle->log = log;//全局log cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle;//old_cycle cycle->conf_prefix.len = old_cycle->conf_prefix.len;//在nginx.c的ngx_process_options中获得 cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) {//配置文件路径为NULL ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len;//在nginx.c的ngx_process_options中获得 cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) {//安装文件夹为NULL ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) {//配置文件相对于安装文件夹的路径为NULL ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1);//拷贝配置文件相对于安装文件夹的路径 cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) {//配置參数 ngx_destroy_pool(pool); return NULL; } n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;//Nginx的操作文件夹个数 cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));//数组申请内存 if (cycle->pathes.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pathes.nelts = 0; cycle->pathes.size = sizeof(ngx_path_t *); cycle->pathes.nalloc = n; cycle->pathes.pool = pool; /*计算open_files的个数*/ if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } //初始化open_files链表。 if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } /*依据old_cycle的shared_memory单链表来初始化cycle的单链表*/ if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } //ngx_list_init主要是初始链表的elts,并为其申请内存 if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;//默认listening的大小为10 /*初始化listening数组*/ cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; //初始化双向链表。主要存储着可反复用的连接ngx_connection_t ngx_queue_init(&cycle->reusable_connections_queue); //初始化conf_ctx,ngx_max_module是nginx中总的模块数 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ //初始化hostname hostname[NGX_MAXHOSTNAMELEN - 1] = '