NGINX源代码自我总结(一)
查看源代码入门
这是一篇关于NGINX的MAIN()函数入门说明文章,相比其他这篇十分枯燥,其实写的时候更是无聊,不过学了这么长时间的WEB开发,连NGINX源代码都没有读下来,总是觉得有些缺憾,希望这一次可以弥补一下。
一、下载NGINX
- 下载地址:http://nginx.org/en/download.html
- tar -zxvf *.tar.gz && ./configure && make && sudo make install
- 查看NGINX目录有如下文件夹:
auto CHANGES CHANGES.ru conf configure contrib html LICENSE Makefile man objs README src
二、使用gdb跟踪查找入口文件
很多朋友看见NGINX目录有很多的内容,就会头疼,不知道从哪里开始,下面就分享一个方法。进入objs目录,会发现nginx是可执行文件,使用gdb跟踪一下(如果没有gdb,执行命令:sudo yum install yum安装即可),依次执行如下命令:
2.1 gdb nginx
进入nginx程序
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-.el6_4.)
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/soft/ngx_openresty-1.4.1.1/build/nginx-1.4./objs/nginx...done.
2.2 l main
目的是查看main函数
(gdb) l main
static char **ngx_os_environ; int ngx_cdecl
main(int argc, char *const *argv)
{
ngx_int_t i;
ngx_log_t *log;
ngx_cycle_t *cycle, init_cycle;
ngx_core_conf_t *ccf;
2.3 i li main
查看main()函数的位置
(gdb) i li main
Line of "src/core/nginx.c" starts at address 0x4168cb <main> and ends at 0x4168e1 <main+>.
如上就知道了入口程序文件是:src/core/nginx.c
三、main()函数
int ngx_cdecl
main(int argc, char *const *argv)
{
ngx_int_t i;
ngx_log_t *log;
ngx_cycle_t *cycle, init_cycle;
ngx_core_conf_t *ccf;
//上面是四个堆栈的常量,没啥别的意思。nginx的结构都是_t结束的。
ngx_debug_init();//nginx的函数都是ngx_开头的。下面有解释 if (ngx_strerror_init() != NGX_OK) {
return ;//如果启动失败
} if (ngx_get_options(argc, argv) != NGX_OK) {
return ;//检测命令行参数异常
} if (ngx_show_version) {//ngx_show_version是一个全局变量,可以在gdb里面查看(p ngx_show_version或者i var ngx_show_version)
ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED); if (ngx_show_help) {//自我帮助信息,执行:"nginx -?"时候输出的信息
ngx_write_stderr(
"Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
"[-p prefix] [-g directives]" NGX_LINEFEED
NGX_LINEFEED
"Options:" NGX_LINEFEED
" -?,-h : this help" NGX_LINEFEED
" -v : show version and exit" NGX_LINEFEED
" -V : show version and configure options then exit"
NGX_LINEFEED
" -t : test configuration and exit" NGX_LINEFEED
" -q : suppress non-error messages "
"during configuration testing" NGX_LINEFEED
" -s signal : send signal to a master process: "
"stop, quit, reopen, reload" NGX_LINEFEED
#ifdef NGX_PREFIX
" -p prefix : set prefix path (default: "
NGX_PREFIX ")" NGX_LINEFEED
#else
" -p prefix : set prefix path (default: NONE)" NGX_LINEFEED
#endif
" -c filename : set configuration file (default: "
NGX_CONF_PATH ")" NGX_LINEFEED
" -g directives : set global directives out of configuration "
"file" NGX_LINEFEED NGX_LINEFEED
);
} if (ngx_show_configure) {
ngx_write_stderr(
#ifdef NGX_COMPILER
"built by " NGX_COMPILER NGX_LINEFEED
#endif
#if (NGX_SSL)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
"TLS SNI support enabled" NGX_LINEFEED
#else
"TLS SNI support disabled" NGX_LINEFEED
#endif
#endif
"configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
} if (!ngx_test_config) {
return ;
}
} /* TODO */ ngx_max_sockets = -; ngx_time_init();//时间初始化 #if (NGX_PCRE)
ngx_regex_init();//宏开关
#endif ngx_pid = ngx_getpid(); log = ngx_log_init(ngx_prefix);//日志初始化
if (log == NULL) {
return ;
} /* STUB */
#if (NGX_OPENSSL)
ngx_ssl_init(log);//ssh初始化
#endif /*
* init_cycle->log is required for signal handlers and
* ngx_process_options()
*/ ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));//init_cycle清零
init_cycle.log = log;
ngx_cycle = &init_cycle; init_cycle.pool = ngx_create_pool(, log);//建立内存池
if (init_cycle.pool == NULL) {
return ;
} if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
return ;
} if (ngx_process_options(&init_cycle) != NGX_OK) {
return ;
} if (ngx_os_init(log) != NGX_OK) {
return ;
} /*
* ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
*/ if (ngx_crc32_table_init() != NGX_OK) {
return ;//crc算法
} if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
return ;
} ngx_max_module = ;
for (i = ; ngx_modules[i]; i++) { //查看一共多少模块
ngx_modules[i]->index = ngx_max_module++;
} cycle = ngx_init_cycle(&init_cycle);//初始化生命周期,下面有讲
if (cycle == NULL) {
if (ngx_test_config) {
ngx_log_stderr(, "configuration file %s test failed",
init_cycle.conf_file.data);
} return ;
} if (ngx_test_config) {
if (!ngx_quiet_mode) {
ngx_log_stderr(, "configuration file %s test is successful",
cycle->conf_file.data);
} return ;
} if (ngx_signal) {
return ngx_signal_process(cycle, ngx_signal);
} ngx_os_status(cycle->log); ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
ngx_process = NGX_PROCESS_MASTER;
} #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) {
return ;
} if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle->log) != NGX_OK) {
return ;
} ngx_daemonized = ;
} if (ngx_inherited) {
ngx_daemonized = ;
} #endif if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
return ;
} if (cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
ngx_set_stderr_n " failed");
return ;
}
} if (log->file->fd != ngx_stderr) {
if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_close_file_n " built-in log failed");
}
} ngx_use_stderr = ; if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle(cycle); } else {
ngx_master_process_cycle(cycle);
} return ;
}
无疑,里面的中文内容肯定是我写的注释。
3.1 ngx_debug_init
使用gdb执行:"i li ngx_debug_init"
(gdb) i li ngx_debug_init
Function "ngx_debug_init" not defined.
(gdb)
没有找到,这个时候只能在文件里面搜索
@~/soft/ngx_openresty-1.4.1.1/build/nginx-1.4./src $ grep -r ngx_debug_init *
core/nginx.c: ngx_debug_init();
os/unix/ngx_freebsd_init.c:ngx_debug_init()
os/unix/ngx_solaris_config.h:#define ngx_debug_init()
os/unix/ngx_linux_config.h:#define ngx_debug_init()
os/unix/ngx_darwin_init.c:ngx_debug_init()
os/unix/ngx_freebsd.h:void ngx_debug_init(void);
os/unix/ngx_posix_config.h:#define ngx_debug_init()
os/unix/ngx_darwin.h:void ngx_debug_init(void);
可见这是一个操作系统相关的内容,先初始化一下。但是什么都没做,所以gdb搜索不到。
3.2 ngx_strerror_init
(gdb) i li ngx_strerror_init
Line of "src/os/unix/ngx_errno.c" starts at address 0x42d8c9 <ngx_strerror_init> and ends at 0x42d8d7 <ngx_strerror_init+>.
然后打开文件ngx_errno.c文件:
ngx_int_t
ngx_strerror_init(void)
{
char *msg;
u_char *p;
size_t len;
ngx_err_t err;
//定义四个堆栈变量
/*
* ngx_strerror() is not ready to work at this stage, therefore,
* malloc() is used and possible errors are logged using strerror().
*/ len = NGX_SYS_NERR * sizeof(ngx_str_t);
//计算长度,注意NGX_SYS_NERR不是在src里面的,而是编译的时候根据操作系统的不同而生成的不内容,这里是在objs/ngx_auto_config.h里面,定义为:135。
ngx_sys_errlist = malloc(len);//申请空间
if (ngx_sys_errlist == NULL) {
goto failed;
} for (err = ; err < NGX_SYS_NERR; err++) {
msg = strerror(err);//如果不是以ngx_开头的,都是系统函数或者其他的库函数。这里是建立一个字符串描述这个错误号
len = ngx_strlen(msg); p = malloc(len);
if (p == NULL) {
goto failed;
} ngx_memcpy(p, msg, len);//系统的错误信息拷贝到自己的空间。
ngx_sys_errlist[err].len = len;
ngx_sys_errlist[err].data = p;
} return NGX_OK; failed: err = errno;
ngx_log_stderr(, "malloc(%uz) failed (%d: %s)", len, err, strerror(err)); return NGX_ERROR;
}
作用是将全局的错误信息复制到一个数组里面,暂时不知道是为什么
3.3 ngx_init_cycle
初始化生命周期。core/ngx_cycle.c,这个函数相当的长。
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
void *rv;
char **senv, **env;
ngx_uint_t i, n;
ngx_log_t *log;
ngx_time_t *tp;
ngx_conf_t conf;
ngx_pool_t *pool;
ngx_cycle_t *cycle, **old;
ngx_shm_zone_t *shm_zone, *oshm_zone;
ngx_list_part_t *part, *opart;
ngx_open_file_t *file;
ngx_listening_t *ls, *nls;
ngx_core_conf_t *ccf, *old_ccf;
ngx_core_module_t *module;
char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday();
tp->sec = ; ngx_time_update(); 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 + );
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 + ); 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->paths.nelts ? old_cycle->paths.nelts : ; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
if (cycle->paths.elts == NULL) {
ngx_destroy_pool(pool);
return NULL;
} cycle->paths.nelts = ;
cycle->paths.size = sizeof(ngx_path_t *);
cycle->paths.nalloc = n;
cycle->paths.pool = pool; 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 = ;
} if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NULL;
} 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 = ;
} 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 : ; 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 = ;
cycle->listening.size = sizeof(ngx_listening_t);
cycle->listening.nalloc = n;
cycle->listening.pool = pool; ngx_queue_init(&cycle->reusable_connections_queue); 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) == -) {
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 - ] = '\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); for (i = ; 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, , 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;
}
//cycle->conf,指向一块内存,多级指针数组,共44个模块。第0个是核心模块的数据结构,ngx_core_module,如后面3.5所示;第3个是一个指向指针的指针,ngx_events_module。
//第六个指向的ngx的http模块,ngx_http_core数据结构,如3.6所示
if (ngx_test_config && !ngx_quiet_mode) {
ngx_log_stderr(, "the configuration file %s syntax is ok", cycle->conf_file.data);
} for (i = ; 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) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
goto failed;
} } else if (!ngx_is_init_cycle(old_cycle)) { /*
* 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) != )
{
/* 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_paths(cycle, ccf->user) != NGX_OK) {
goto failed;
} 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 */ part = &cycle->open_files.part;
file = part->elts; for (i = ; /* void */ ; i++) { if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = ;
} if (file[i].name.len == ) {
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, ,
"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) == -) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"fcntl(FD_CLOEXEC) \"%s\" failed",
file[i].name.data);
goto failed;
}
#endif
} cycle->log = &cycle->new_log;
pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part;
shm_zone = part->elts; for (i = ; /* void */ ; i++) { if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
shm_zone = part->elts;
i = ;
} if (shm_zone[i].shm.size == ) {
ngx_log_error(NGX_LOG_EMERG, log, ,
"zero size shared memory zone \"%V\"",
&shm_zone[i].shm.name);
goto failed;
} shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part;
oshm_zone = opart->elts; for (n = ; /* void */ ; n++) { if (n >= opart->nelts) {
if (opart->next == NULL) {
break;
}
opart = opart->next;
oshm_zone = opart->elts;
n = ;
} 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)
!= )
{
continue;
} if (shm_zone[i].tag == oshm_zone[n].tag
&& 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;
} /* handle the listening sockets */ if (old_cycle->listening.nelts) {
ls = old_cycle->listening.elts;
for (i = ; i < old_cycle->listening.nelts; i++) {
ls[i].remain = ;
} nls = cycle->listening.elts;
for (n = ; n < cycle->listening.nelts; n++) { for (i = ; i < old_cycle->listening.nelts; i++) {
if (ls[i].ignore) {
continue;
} if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].previous = &ls[i];
ls[i].remain = ; if (ls[n].backlog != nls[i].backlog) {
nls[n].listen = ;
} #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /*
* FreeBSD, except the most recent versions,
* could not remove accept filter
*/
nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) {
if (ngx_strcmp(ls[i].accept_filter,
nls[n].accept_filter)
!= )
{
nls[n].delete_deferred = ;
nls[n].add_deferred = ;
} } else if (ls[i].accept_filter) {
nls[n].delete_deferred = ; } else if (nls[n].accept_filter) {
nls[n].add_deferred = ;
}
#endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) {
nls[n].delete_deferred = ; } else if (ls[i].deferred_accept != nls[n].deferred_accept)
{
nls[n].add_deferred = ;
}
#endif
break;
}
} if (nls[n].fd == -) {
nls[n].open = ;
}
} } else {
ls = cycle->listening.elts;
for (i = ; i < cycle->listening.nelts; i++) {
ls[i].open = ;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
if (ls[i].accept_filter) {
ls[i].add_deferred = ;
}
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
if (ls[i].deferred_accept) {
ls[i].add_deferred = ;
}
#endif
}
} if (ngx_open_listening_sockets(cycle) != NGX_OK) {
goto failed;
} if (!ngx_test_config) {
ngx_configure_listening_sockets(cycle);
} /* commit the new cycle configuration */ if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
ngx_set_stderr_n " failed");
}
} pool->log = cycle->log; for (i = ; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_module) {
if (ngx_modules[i]->init_module(cycle) != NGX_OK) {
/* fatal */
exit();
}
}
} /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part;
oshm_zone = opart->elts; for (i = ; /* void */ ; i++) { if (i >= opart->nelts) {
if (opart->next == NULL) {
goto old_shm_zone_done;
}
opart = opart->next;
oshm_zone = opart->elts;
i = ;
} part = &cycle->shared_memory.part;
shm_zone = part->elts; for (n = ; /* void */ ; n++) { if (n >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
shm_zone = part->elts;
n = ;
} if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len
&& ngx_strncmp(oshm_zone[i].shm.name.data,
shm_zone[n].shm.name.data,
oshm_zone[i].shm.name.len)
== )
{
goto live_shm_zone;
}
} ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue;
} old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts;
for (i = ; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == -) {
continue;
} if (ngx_close_socket(ls[i].fd) == -) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " listening socket on %V failed",
&ls[i].addr_text);
} #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) {
u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - ; ngx_log_error(NGX_LOG_WARN, cycle->log, ,
"deleting socket %s", name); if (ngx_delete_file(name) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_delete_file_n " %s failed", name);
}
} #endif
} /* close the unnecessary open files */ part = &old_cycle->open_files.part;
file = part->elts; for (i = ; /* void */ ; i++) { if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = ;
} if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
continue;
} if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_close_file_n " \"%s\" failed",
file[i].name.data);
}
} ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /*
* perl_destruct() frees environ, if it is not the same as it was at
* perl_construct() time, therefore we save the previous cycle
* environment before ngx_conf_parse() where it will be changed.
*/ env = environ;
environ = senv; ngx_destroy_pool(old_cycle->pool);
cycle->old_cycle = NULL; environ = env; return cycle;
} if (ngx_temp_pool == NULL) {
ngx_temp_pool = ngx_create_pool(, cycle->log);
if (ngx_temp_pool == NULL) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ,
"could not create ngx_temp_pool");
exit();
} n = ;
ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
n * sizeof(ngx_cycle_t *));
if (ngx_old_cycles.elts == NULL) {
exit();
}
ngx_old_cycles.nelts = ;
ngx_old_cycles.size = sizeof(ngx_cycle_t *);
ngx_old_cycles.nalloc = n;
ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles;
ngx_cleaner_event.log = cycle->log;
ngx_cleaner_event.data = &dumb;
dumb.fd = (ngx_socket_t) -;
} ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles);
if (old == NULL) {
exit();
}
*old = old_cycle; if (!ngx_cleaner_event.timer_set) {
ngx_add_timer(&ngx_cleaner_event, );
ngx_cleaner_event.timer_set = ;
} return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) {
old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,ngx_core_module);
if (old_ccf->environment) {
environ = old_ccf->environment;
}
} /* rollback the new cycle configuration */ part = &cycle->open_files.part;
file = part->elts; for (i = ; /* void */ ; i++) { if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = ;
} if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
continue;
} if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_close_file_n " \"%s\" failed",
file[i].name.data);
}
} if (ngx_test_config) {
ngx_destroy_cycle_pools(&conf);
return NULL;
} ls = cycle->listening.elts;
for (i = ; i < cycle->listening.nelts; i++) {
if (ls[i].fd == - || !ls[i].open) {
continue;
} if (ngx_close_socket(ls[i].fd) == -) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[i].addr_text);
}
} ngx_destroy_cycle_pools(&conf); return NULL;
}
修改配置参数之后,可以不重新启动服务,而可以生效。他把所有nginx的参数都放入到一个参数里面,如果修改,那么他会慢慢的修改过来。
3.4 ngx_cycle_s
文件:src/core/ngx_cycle.h
struct ngx_cycle_s {
void ****conf_ctx;//解析配置文件,
ngx_pool_t *pool;
ngx_log_t *log;
ngx_log_t new_log;
ngx_connection_t **files;
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
ngx_queue_t reusable_connections_queue;
ngx_array_t listening;
ngx_array_t paths;
ngx_list_t open_files;
ngx_list_t shared_memory;
ngx_uint_t connection_n;
ngx_uint_t files_n;
ngx_connection_t *connections;
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;
};
3.5 ngx_core_conf_t 结构体
typedef struct {
ngx_flag_t daemon;
ngx_flag_t master;
ngx_msec_t timer_resolution;
ngx_int_t worker_processes; //进程数量
ngx_int_t debug_points;
ngx_int_t rlimit_nofile;
ngx_int_t rlimit_sigpending;
off_t rlimit_core;
int priority;
ngx_uint_t cpu_affinity_n;
uint64_t *cpu_affinity;
char *username;
ngx_uid_t user;
ngx_gid_t group;
ngx_str_t working_directory;
ngx_str_t lock_file;
ngx_str_t pid;
ngx_str_t oldpid;
ngx_array_t env;
char **environment;
#if (NGX_THREADS)
ngx_int_t worker_threads;
size_t thread_stack_size;
#endif
} ngx_core_conf_t;
3.6 ngx_http_conf_cxt_t结构体
在src/http/ngx_http_config.h里面
typedef struct {
void **main_conf; //http的子模块
void **srv_conf; //所有server的参数
void **loc_conf; //所有url的参数
} ngx_http_conf_ctx_t;
NGINX源代码自我总结(一)的更多相关文章
- NGINX源代码剖析 之 CPU绑定(CPU亲和性)
作者:邹祁峰 邮箱:Qifeng.zou.job@gmail.com 博客:http://blog.csdn.net/qifengzou 日期:2014.06.12 18:44 转载请注明来自&quo ...
- nginx源代码学习资源(不断更新)
nginx源代码学习是一个痛苦又快乐的过程,以下列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源代码,能够从nginx官方站点下载一份最新的. 看了nginx源代码,发现这是一份 ...
- 菜鸟nginx源代码剖析数据结构篇(一)动态数组ngx_array_t
菜鸟nginx源代码剖析数据结构篇(一)动态数组ngx_array_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...
- 新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t
新秀nginx源代码分析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...
- 新秀nginx源代码分析数据结构篇(两) 双链表ngx_queue_t
nginx源代码分析数据结构篇(两) 双链表ngx_queue_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn. ...
- 菜鸟nginx源代码剖析数据结构篇(八) 缓冲区链表ngx_chain_t
菜鸟nginx源代码剖析数据结构篇(八) 缓冲区链表 ngx_chain_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog. ...
- nginx源代码分析之内存池实现原理
建议看本文档时结合nginx源代码. 1.1 什么是内存池?为什么要引入内存池? 内存池实质上是接替OS进行内存管理.应用程序申请内存时不再与OS打交道.而是从内存池中申请内存或者释放内存到内存池 ...
- Nginx源代码分析—业务流程
Nginx源代码分析-业务流程 到此为止,我们如果ngx_init_cycle已经结束.我们临时无论他做了什么,我们从他做的效果进入. 从常理上来讲,假设一个请求到达,那么我们须要接受这个请求,那么就 ...
- 《nginx源代码解析》系列分享专栏
<nginx源代码解析>系列分享专栏 解析nginx源代码,从main函数开始,一步步解读nginx运行原理,同时进行nginx第三方模块的开发,努力做到知其然,知其所以然 <ngi ...
随机推荐
- C++ inline内联函数
inline 函数避免函数调用的开销 // find longer of two strings const string &shorterString(const string &s ...
- Linux学习20-nohup挂后台启动django
前言 django在linux上运行,一般在xshell远程连接后,是通过python manage.py runserver 0.0.0.0:8000启动服务.但是这样有个弊端,窗口关闭服务就停止了 ...
- 根据UIScrollView的contentOffset值精确控制动画
根据UIScrollView的contentOffset值精确控制动画 效果 原理 根据方程精确计算每一个view在位移值x变化的时候的输出值,并根据这个值实现各种逻辑. 源码 https://git ...
- 破产姐妹第六季/全集2 Broke Girls迅雷下载
英文全名2 Broke Girls,第6季(2016)CBS. 本季看点:<破产姐妹>第五季季终集达到了收视人数699万收视率1.7.在第五季终集,两姐妹发现Han(马修·摩伊 饰)的生活 ...
- 尼基塔第一季/全集Nikita迅雷下载
本季Nikita Season 1 第一季(2010)看点:尼基塔曾经是一个性格叛逆的问题少女,因为犯下重罪被处以死刑.一家秘密间谍机构将尼基塔从死牢里救了出来,伪造了她的死亡,将她训练成了一名间谍和 ...
- Linux常用命令汇总 - Linux Shell Cheat Sheet
1. 查看Linux操作系统信息: uname -a cat /proc/version lsb_release -a 2. 设置ls显示的文件夹的颜色(将下面这条目录加在 .bashrc 文件最后) ...
- LCA算法总结
LCA问题(Least Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找 ...
- SpringMVC request生命周期
When the request leaves the browser, it carries information about what the user is asking for. At ve ...
- WinPcap权威指南(三):ARP协议
ARP协议在局域网内使用的非常广泛,它的数据包类型分为请求包和答复包.Windows系统内部有一个缓冲区,保存了最近的ARP信息,可以在cmd下使用命令arp -a来显示目前的缓存,或者使用命令arp ...
- Asp.net WebAPi Restful 的实现和跨域
现在实际开发中用webapi来实现Restful接口开发很多,我们项目组前一段时间也在用这东西,发现大家用的还是不那么顺畅,所以这里写一个Demo给大家讲解一下,我的出发点不是如何实现,而是为什么? ...