在系统整个运行过程中,需要使用的一些参数、资源需要统一的管理,nginx把这个任务交给了ngx_cycle_t
struct ngx_cycle_s { void ****conf_ctx; //指向模块的配置 ngx_pool_t *pool; //内存池 ngx_log_t *log; //日志 ngx_log_t new_log; //新日志 ngx_connection_t **files; //存放socket和connection之间的关系 ngx_connection_t *free_connections; //空闲连接池 ngx_uint_t free_connection_n; //空闲连接的个数 ngx_array_t listening; //监听者 ngx_array_t pathes; //系统所使用的路径集合 ngx_list_t open_files; //打开文件的集合 ngx_list_t shared_memory; //共享内存 ngx_uint_t connection_n; //总的预先创建的connection数目 ngx_uint_t files_n; //总文件数目 ngx_connection_t *connections; //所有的connection ngx_event_t *read_events; //读事件 ngx_event_t *write_events; //写事件 ngx_cycle_t *old_cycle; //旧的全局信息 ngx_str_t conf_file; //配置文件 ngx_str_t conf_param; //配置参数 ngx_str_t conf_prefix; //配置文件前缀 ngx_str_t prefix; //系统安装路径前缀 ngx_str_t lock_file; //锁文件 ngx_str_t hostname; //主机名 }
conf_ctx 指向模块的配置
pool 内存池
log 日志
new_log 新日志
files 存放socket和connection之间的关系
free_connections 空闲连接池
free_connection_n 空闲连接的个数
listening 监听者,用于监听外部的连接。
pathes 整个系统中使用的路径集合,比如 client_body_temp ,proxy_temp 等,这个也是在nginx_cycle.c 中的ngx_init_cycle中分配的,和上面listening分配方式差不多,实际路径的添加是在 ngx_file.c 中的 ngx_add_path 函数中
open_files 打开文件的集合,当需要打开一个文件时,先在这里找,如果找到直接返回,否则打开文件,放到这个集合中。文件代开在ngx_conf_file.c中的ngx_conf_open_file函数中实现的
shared_memory 系统所有的共享内存,如果往里面添加共享内存,需要检查下是否已经存在了,存在就不用放了,否则就放进去,在函数ngx_shared_memory_add函数中实现。
connection_n; 总的预先创建的connection数目
files_n 总的文件数目,不过好像没有设置,待确认
connections 所有的连接,free_connection也是指向它所指向的空间的
read_events write_events 读写事件,他们的个数和connection一样的,并且在初始化的时候,一个connection关联一个读事件、一个写事件。
old_cycle 旧的全局信息
conf_file 配置文件,如果系统默认,那么直接从objs/ngx_auto_conf.h中读取,也可以在通过参数设定
conf_param; 配置参数
conf_prefix; 配置文件前缀
prefix; 系统安装路径前缀
lock_file; 锁文件
hostname; 主机名
整个结构的初始化在nginx.c 中的ngx_init_cycle 中进行,下面介绍下这个函数
//更新时间 ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update(0, 0); //创建内存池,并把日志和它关联 log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; //分配内存,并把内存池、日志、旧信息以及路径进行了设置 cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle; //配置路径的前缀 cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } //系统路径的前缀 cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == 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) { 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; 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; //如果原来结构中有文件,那么直接统计原来打开的文件,否则默认20 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; } //根据数量初始化 if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } //如果原来结构中共享内存,那么直接统计原来共享内存数,否则默认20 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; } //根据数量初始化 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; 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; //创建所有模块配置的指针 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } //设置 host 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[NGX_MAXHOSTNAMELEN - 1] = '/0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); //调用核心模块的配置创建函数, cycle->conf_ctx 中对应的指针指向创建的配置 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; //对指令结构进行初始化:参数,内存池 ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } //指令结果赋值 conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif //处理配置参数 if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } //解析配置文件 if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_test_config) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } //调用核心模块配置的初始化函数 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } //这个是判断启动的类型,启动、重启、。。。。。但是为什么退出还没看懂 if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { //只是测试配置文件,就创建pid文件 if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { //第一次启动的时候,暂时不创建pid文件,因为需要向里面写守护进程的pid /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } //测试锁文件 if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } //对路径集中的每个路径,创建目录 if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) { goto failed; } //建立new_log文件 if (cycle->new_log.file == NULL) { cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); if (cycle->new_log.file == NULL) { goto failed; } } /* open the new files */ //打开open_files集合中的所有文件,并保存文件句柄 part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d /"%s/"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " /"%s/" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) /"%s/" failed", file[i].name.data); goto failed; } #endif } //更新log cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ //创建共享内存 part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } / if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone /"%V/"", &shm_zone[i].shm.name); goto failed; } if (shm_zone[i].init == NULL) { /* unused shared zone */ continue; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } //原来的共享内存中是否有相同名字的, //首先是看名字长度再进行名字的对比 if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].shm.size == oshm_zone[n].shm.size) { //如果大小也相同,那么直接可以拿来用了 shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } //名字相同的已经存在,但是大小不一样,所以把原来那个个释放,重新分配 ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { //分配共享内存 goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; }
最后还剩下一部分比较乱,下次来补充