nginx启动过程如下。
1.调用ngx_strerror_init()初始化错误列表
strerror(errno)该函数以errno为下标返回错误值,这样初始化的好处是每次出错的时候不用再次调用strerror函数来获取错误原因,而直接根据错误编号找到对应得错误原因,提高执行效率,即他已经存放在一个数组中
2.调用ngx_get_options()解析命令参数;
解析nginx的启动参数,内部的函数是通过对字符串的判断,设置相应的变量,比如如果发现了-v就把设置ngx_show_version=1,那么就会显示它的版本信息。类似的还有ngx_show_configure、它内部是一个while循环,因为他可能会有多个启动参数需要解析,依次赋值给那些全局变量
-p:ngx_prefix
-c:ngx_conf_file
-g:ngx_conf_params
-s:ngx_signal
3.调用ngx_time_init()初始化并更新时间,如全局变量ngx_cached_time;
4.调用ngx_log_init()初始化日志,如初始化全局变量ngx_prefix,打开日志文件ngx_log_file.fd;
5.清零全局变量ngx_cycle,并为ngx_cycle.pool创建大小为1024B的内存池;
6.调用ngx_save_argv()保存命令行参数至全局变量ngx_os_argv、ngx_argc、ngx_argv中;
7.调用ngx_process_options()初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等字段;
8.调用ngx_os_init()初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等;
9.调用ngx_crc32_table_init()初始化CRC表(后续的CRC校验通过查表进行,效率高);
10.调用ngx_add_inherited_sockets()继承sockets,该函数主要处理的就是继承的socket
该函数通过解析环境变量NGINX_VAR=”NGINX”,将其中的socket number保存至ngx_cycle.listening数组,该数组元素类型为ngx_listening_t。这些socekts在环境变量中以’:’或’;’隔开
{
inherited = (u_char ) getenv(NGINX_VAR); / NGINX_VAR为宏,值为”NGINX” *
ls = ngx_array_push(&cycle->listening);
ngx_memzero(ls, sizeof(ngx_listening_t));
ls->fd = (ngx_socket_t) s; /* 保存该socket至listening数组元素的fd字段 */
return ngx_set_inherited_sockets(cycle); /* 该函数逐一设置cycle->listening数组每个元素 */
}
Ngx_set_inherited_sockets()
{
该函数从参数cycle(后续调用ngx_init_cycle()函数后全局变量ngx_cycle会指向该参数)的listening数组中逐一对每个元素(ngx_listening_t结构)进行初始化,即初始化除fd字段外的其他的字段。
对全局变量ngx_cycle的listening数组,逐一设置该数组每个元素的以下字段
• ls[i].sockaddr (调用getsockname())
• ls[i].addr_text_max_len
• ls[i].addr_text
• ls[i].backlog
• ls[i].rcvbuf (调用getsockopt())
• ls[i].sndbuf (调用getsockopt())
• ls[i].accept_filter
• ls[i].deferred_accept
涉及到的相关系统函数调用如下。
• getenv()获取环境变量,并返回指向该值字符串的指针;
• getsockname()获取socket名字(地址及长度);
• getsockopt()获取socket选项;
}
11.初始化每个module的index,并计算ngx_max_module
12. 调用ngx_init_cycle()进行初始化
详细见nginx_cycle_t的初始化
13.若有信号,则进入ngx_signal_process()处理
14.调用ngx_init_signals()初始化信号;主要完成信号处理程序的注册
详细见nginx信号的使用
15.若无继承sockets,且设置了守护进程标识,则调用ngx_daemon()创建守护进程;
16.调用ngx_create_pidfile()创建进程记录文件;(非NGX_PROCESS_MASTER=1进程,不创建该文件)
17.通过ngx_process的值确定使用哪种进程模式
若为NGX_PROCESS_SINGLE=1模式,则调用ngx_single_process_cycle()进入进程循环;
否则为master-worker模式,调用ngx_master_process_cycle()进入进程循环;