本文主要是介绍nginx 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;
/*
第一个函数ngx_debug_init(),这个函数主要是作为初始化debug用的,nginx中的debug,主要是对内存池分配管理方面的debug,因为作为一个应用程序,最容易出现bug的地方也是内存管理这块。在Linux版本中,这个函数只是一个空定义(src/os/unix/ngx_linux_config.h)。
#define ngx_debug_init()
*/
ngx_debug_init();
/*
*我们来到程序的第208行,ngx_strerror_init(),该函数的定义在文件src/os/unix/ngx_errno.c中。
*该函数主要初始化系统中错误编号对应的含义,这样初始化中进行对应的好处是,当出现错误,
*不用再去调用strerror()函数来获取错误原因,而直接可以根据错误编号找到对应的错误原因,
*可以提高运行时的执行效率。从这里可以看到,nginx开发者的别有用心,对于微小的性能提升也毫不放过。 */
if (ngx_strerror_init() != NGX_OK) {
return 1;
}
//获得运行时选项
if (ngx_get_options( argc, argv ) != NGX_OK) {
return 1;
}
if (ngx_show_version) {
ngx_write_stderr( "nginx version: " NGINX_VER NGX_LINEFEED );
if (ngx_show_help) {
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 0;
}
}
/* TODO */ ngx_max_sockets = -1;
//初始化系统时间
ngx_time_init();
#if (NGX_PCRE)
ngx_regex_init();
#endif
ngx_pid = ngx_getpid();
//初始化日志信息
log = ngx_log_init(ngx_prefix);
if (log == NULL) {
return 1;
}
/* STUB */
#if (NGX_OPENSSL)
ngx_ssl_init( log);
#endif
/*
* init_cycle->log is required for signal handlers and
* ngx_process_options()
*/
/*
ngx_string.h 第86行
#define ngx_memzero(buf, n) (void) memset(buf, 0, n)
ngx_cycle_s 机构体:ngx_cycle.h 第37行
*/
ngx_memzero(& init_cycle, sizeof (ngx_cycle_t));
//开始初始化ngx_cycle_s *init_cycle对象
init_cycle. log = log ;
ngx_cycle = & init_cycle;
// 为ngx_cycle 创建内存池 ,ngx_pool我们在另一篇博客中再讲
init_cycle. pool = ngx_create_pool(1024, log );
if (init_cycle. pool == NULL ) {
return 1;
}
// 保存进程参数到init_cycle中
if (ngx_save_argv(& init_cycle, argc , argv) != NGX_OK) {
return 1;
}
// 处理进程参数
if (ngx_process_options(& init_cycle) != NGX_OK) {
return 1;
}
// 获取系统配置信息 (分页大小,CPU 个数,CPU 制造商,文件符最大数等)
if (ngx_os_init( log) != NGX_OK) {
return 1;
}
/*
* ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
*/
// 初始化循环冗余检验表,验证接收数据
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
//通过环境变量NGINX完成socket的继承,这些继承来的socket会放到init_cycyle的listening数组中。
if (ngx_add_inherited_sockets(& init_cycle) != NGX_OK) {
return 1;
}
ngx_max_module = 0;
/**
* nginx把所有模块(ngx_module_t)存放到ngx_modules数组中,这个数组在nginx源码路
* 径的objs/ngx_modules.c中,是在运行configure脚本后生成的。index属性就是该模块
* 在ngx_modules数组中的下标。同时nginx把所有的core module的配置结构存放到ngx_cycle的
* conf_ctx数组中,index也是该模块的配置结构在ngx_cycle->conf_ctx数组中的下标。
**/
for (i = 0; ngx_modules[ i]; i ++) {
ngx_modules[ i]->index = ngx_max_module++;
}
// 初始化init cycle 变量,这是个牛逼的结构
cycle = ngx_init_cycle(& init_cycle);
if (cycle == NULL) {
if (ngx_test_config) {
ngx_log_stderr(0, "configuration file %s test failed" ,
init_cycle.conf_file .data);
}
return 1;
}
if (ngx_test_config) {
if (!ngx_quiet_mode) {
ngx_log_stderr(0, "configuration file %s test is successful" ,
cycle->conf_file .data);
}
return 0;
}
if (ngx_signal) {
return ngx_signal_process(cycle , ngx_signal);
}
ngx_os_status( cycle->log );
ngx_cycle = cycle;
// 获取core module 的配置指针
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 1;
}
if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle ->log) != NGX_OK) {
return 1;
}
ngx_daemonized = 1;
}
if (ngx_inherited) {
ngx_daemonized = 1;
}
#endif
if (ngx_create_pidfile(& ccf->pid , cycle-> log) != NGX_OK) {
return 1;
}
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 1;
}
}
//检查log文件句柄
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 = 0;
if (ngx_process == NGX_PROCESS_SINGLE) {
ngx_single_process_cycle( cycle);
} else {
ngx_master_process_cycle( cycle);
}
return 0;
}
这篇关于nginx main流程分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!