您的位置:首页 > 运维架构 > Nginx

nginx源码解析一(main函数分析)

2015-12-31 16:22 981 查看
//1.时间、正则、错误日志、ssl等初始化
//2.读入命令行参数
//3.OS相关初始化
//4.读入并解析配置
//5.核心模块初始化
//6.创建各种临时文件和目录
//7.创建共享内存
//8.打开listen的端口
//9.所有模块初始化
//10.启动worker进程
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;

#if (NGX_FREEBSD)
ngx_debug_init();
#endif

if (ngx_strerror_init() != NGX_OK) {
return 1;
}

//获取参数和配置参数,比如命令是nginx -v 那么ngx_show_version就设置为1
if (ngx_get_options(argc, argv) != NGX_OK) {
//读取服务器启动时后跟的参数,根据参数来设置一些全局变量(例如有-v时,设置
//ngx_show_version=1),从而来控制后面的执行流程
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;

//初始化nginx环境的当前时间
ngx_time_init();

#if (NGX_PCRE)
ngx_regex_init();
#endif

//master pid, 获取当前进程ID
ngx_pid = ngx_getpid();
// 初始化日志,如打开日志文件
log = ngx_log_init(ngx_prefix);
if (log == NULL) {
return 1;
}

/* STUB */
#if (NGX_OPENSSL)
ngx_ssl_init(log);  //是否开启了ssl,如果开启在这里进行初始化
#endif

/*
* init_cycle->log is required for signal handlers and
* ngx_process_options()
*/

ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
init_cycle.log = log;
ngx_cycle = &init_cycle;
// 为cycle创建一个1024B的内存池
init_cycle.pool = ngx_create_pool(1024, log);
if (init_cycle.pool == NULL) {
return 1;
}
// 保存参数到全局变量中
if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
return 1;
}
// 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段
if (ngx_process_options(&init_cycle) != NGX_OK) {
return 1;
}
// 初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
if (ngx_os_init(log) != NGX_OK) {  // 这个ngx_os_init在不同操作系统调用不同的函数
return 1;
}

/*
* ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
*/
// 初始化CRC表,提高效率,以后就不用计算了,直接用
if (ngx_crc32_table_init() != NGX_OK) {
return 1;
}
// 继承sockets,继承来的socket将会放到init_cycle的listening数组
if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
return 1;
}
// 计算模块个数,并且设置各个模块顺序(索引)
ngx_max_module = 0;
for (i = 0; ngx_modules[i]; i++) {  // 这里面的ngx_modules会有非常多的模块,[ngx_core_module,ngx_errlog_module,ngx_conf_moduel]
ngx_modules[i]->index = ngx_max_module++;
}

// 对ngx_cycle结构进行初始化,这里是nginx启动核心之处!
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;
}
// 检查是否有设置信号处理,如有,进入ngx_signal_process处理
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 1;
}

if (!ngx_inherited && ccf->daemon) {
if (ngx_daemon(cycle->log) != NGX_OK) { //如果是daemon模式,本进程变为守护进程
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;
}
}

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);    //多进程,master进程进入这个,这个函数在不同操作系统有不同实现。
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: