Content
- 序
- main()分析
- 注意问题
2.1 几个初值
2.2 nginx工作模式
2.3 一些配置
2.4 其他开关
3. 小结
0.序
本文主要分析
nginx
主程序。
nginx
主程序
main()
实现文件:
./src/core/nginx.c
。
.
表示
nginx-1.0.4
代码目录,本文为
/usr/src/nginx-1.0.4
。
1. main()
分析
nginx
启动过程如下。
- 调用
ngx_get_options
()
解析命令参数;
- 调用
ngx_time_init
()
初始化并更新时间,如全局变量
ngx_cached_time
;
- 调用
ngx_log_init
()
初始化日志,如初始化全局变量
ngx_prefix
,打开日志文件
ngx_log_file.fd
;
- 清零全局变量
ngx_cycle
,并为
ngx_cycle
.pool
创建大小为
1024B
的内存池;
- 调用
ngx_save_argv
()
保存命令行参数至全局变量
ngx_os_argv
、
ngx_argc
、
ngx_arg
v
中;
- 调用
ngx_process_options
()
初始化
ngx_cycle
的
prefix, conf_prefix, conf_file, conf_param
等字段;
- 调用
ngx_os_init
()
初始化系统相关变量,如内存页面大小
ngx_pagesize
,
ngx_cacheline_size
,
最大连接数
ngx_max_sockets
等;
- 调用
ngx_crc32_table_init
()
初始化
CRC
表
(
后续的
CRC
校验通过查表进行,效率高
)
;
- 调用
ngx_add_inherited_sockets
()
继承
sockets
;
- 解析环境变量
NGINX_VAR="NGINX"
中的
sockets
,并保存至
ngx_cycle
.listening
数组;
* 设置
ngx_inherited
=1
;
- 调用
ngx_set_inherited_sockets
()
逐一对
ngx_cycle.listening
数组中的
sockets
进行设置;
- 具体可参考
<nginx
源码分析—初始化过程中处理继承的
sockets>
- 初始化每个
module
的
index
,并计算
ngx_max_module
;具体可参考<nginx源码分析—模块及其初始化>
;
- 调用
ngx_init_cycle
()
进行初始化;
- 该初始化主要对
ngx_cycle
结构进行;
- 具体可参考
<nginx
源码分析—全局变量
ngx_cycle
的初始化
;
- 若有信号,则进入
ngx_signal_process
()
处理;
- 调用
ngx_init_signals
()
初始化信号;主要完成信号处理程序的注册;
- 若无继承
sockets
,且设置了守护进程标识,则调用
ngx_daemon()
创建守护进程;
- 调用
ngx_create_pidfile
()
创建进程记录文件;
(
非
NGX_PROCESS_MASTER
=1
进程,不创建该文件
)
-
进入进程主循环;
-
若为
NGX_PROCESS_SINGLE
=1
模式,则调用
ngx_single_process_cycle
()
进入进程循环;
- 否则为
master-worker
模式,调用
ngx_master_process_cycle
()
进入进程循环;
简要的函数调用图如下。具体的还是需要阅读源代码。
。
2. 注意问题
2.1 几个初值
00353: ngx_cycle = cycle;
/* cycle是调用ngx_init_cycle()的返回值,而调用该函数的参数也是ngx_cycle */
1.
00354:
1.
00355: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
1.
00356:
1.
00357:
if
(ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
/* ccf->master=-1 */
1.
00358: ngx_process = NGX_PROCESS_MASTER;
1.
00359: }
此处单独将该段代码拿出来,说明以下问题。
ngx_process在此处的值是什么?——NGX_PROCESS_SINGLE=0
ccf->master在此处的值之什么?——NGX_CONF_UNSET=-1
ngx_prefix何时初始化的?——ngx_log_init()中初始化
(1)ccf->master
ccf->master的值是在ngx_init_cycle()函数中调用NGX_CORE_MODULE模块的create_conf钩子(callback)完成初始化的。
(2)ngx_process
ngx_process是全局变量,定义如下。
//./src/os/unix/ngx_process_cycle.c
1.
ngx_uint_t ngx_process;
1.
ngx_pid_t ngx_pid;
1.
ngx_uint_t ngx_threaded;
其在ngx_init_cycle()中没有被初始化,故其初值为0。
(3)ngx_prefix
[cpp] view plain copy
static
u_char *ngx_prefix;
/* nginx工作目录,默认为/usr/local/nginx/ */
1.
static
u_char *ngx_conf_file;
/* 配置文件 */
1.
static
u_char *ngx_conf_params;
/* nginx指令 */
在ngx_log_init()中初始化。
实际上,在main()函数开始调用的ngx_get_options()函数,即是处理nginx启动的命令,并从中获取参数并赋予相应的变量。
-p:ngx_prefix
-c:ngx_conf_file
-g:ngx_conf_params
-s:ngx_signal
关于这一点,可从以下命令结果看出端倪。
[plain] view plain copy
# ./nginx -h
1.
nginx: nginx version: nginx/1.0.4
1.
nginx: Usage: nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]
1.
1.
Options:
1.
-?,-h : this help
1.
-v : show version and exit
1.
-V : show version and configure options then exit
1.
-t : test configuration and exit
1.
-q : suppress non-error messages during configuration testing
1.
-s signal : send signal to a master process: stop, quit, reopen, reload
1.
-p prefix : set prefix path (default: /usr/local/nginx/)
1.
-c filename : set configuration file (default: conf/nginx.conf)
1.
-g directives : set global directives out of configuration file
2.2 nginx工作模式
因此,main()函数返回前调用ngx_master_process_cycle()函数进入多进程(master/worker)工作模式。如下。
00401:
if
(ngx_process == NGX_PROCESS_SINGLE) {
/* 单进程 */
1.
00402: ngx_single_process_cycle(cycle);
1.
00403:
1.
00404: }
else
{
/* 多进程 */
1.
00405: ngx_master_process_cycle(cycle);
1.
00406: }
具体请参考<nginx源码分析—master/worker进程启动>。
2.3 一些配置
看源代码时,会注意到有些宏(宏全部大写,中间用下划线隔开,这是nginx代码规范。实际上,绝大多数系统均采用此规范)找不到定义,例如NGX_PREFIX、NGX_CONF_PREFIX、NGX_CONF_PATH等。
实际上,这些宏定义由configure程序进行自动配置时生成。配置时会自动生成ngx_auto_config.h文件(如果你用source insight阅读源代码,需要将该文件加入工程),如下。
./objs/ngx_auto_config.h(此处列出其中一部分常用的宏,未按顺序)
#ifndef NGX_COMPILER
1.
#define NGX_COMPILER "gcc 4.6.1 20110908 (Red Hat 4.6.1-9) (GCC) "
1.
#endif
1.
1.
#ifndef NGX_PCRE
1.
#define NGX_PCRE 1
1.
#endif
1.
1.
#ifndef NGX_PREFIX
1.
#define NGX_PREFIX "/usr/local/nginx/"
1.
#endif
1.
1.
#ifndef NGX_CONF_PREFIX
1.
#define NGX_CONF_PREFIX "conf/"
1.
#endif
1.
1.
#ifndef NGX_CONF_PATH
1.
#define NGX_CONF_PATH "conf/nginx.conf"
1.
#endif
1.
1.
#ifndef NGX_PID_PATH
1.
#define NGX_PID_PATH "logs/nginx.pid"
1.
#endif
1.
1.
#ifndef NGX_LOCK_PATH
1.
#define NGX_LOCK_PATH "logs/nginx.lock"
1.
1.
#ifndef NGX_ERROR_LOG_PATH
1.
#define NGX_ERROR_LOG_PATH "logs/error.log"
1.
#endif
1.
1.
#ifndef NGX_HTTP_LOG_PATH
1.
#define NGX_HTTP_LOG_PATH "logs/access.log"
1.
#endif
1.
1.
#ifndef NGX_HTTP_CLIENT_TEMP_PATH
1.
#define NGX_HTTP_CLIENT_TEMP_PATH "client_body_temp"
1.
#endif
1.
1.
#ifndef NGX_HTTP_PROXY_TEMP_PATH
1.
#define NGX_HTTP_PROXY_TEMP_PATH "proxy_temp"
1.
#endif
2.4 其他开关
还有一些开关,如NGX_FREEBSD, NGX_PCRE,NGX_OPENSSL等,这些宏也在configure过程中自动配置。nginx启动时会根据这些宏是否定义调用相应的函数。此处非本文重点,不再赘述。
以上3个宏分别调用相应函数进行debug的初始化、正则表达式初始化和SSL的初始化。如下。(代码未按顺序)
#if (NGX_FREEBSD)
1.
ngx_debug_init();
1.
#endif
1.
1.
#if (NGX_PCRE)
1.
ngx_regex_init();
1.
#endif
1.
1.
#if (NGX_OPENSSL)
1.
ngx_ssl_init(log);
1.
1.
#endif
3. 小结
本文简单分析nginx的启动过程,后文继续分析其中的ngx_init_cycle()和master/worker工作模型。