0. 序
1. main()分析
2. 注意问题
2.1 几个初值
2.2 nginx工作模式
2.3 一些配置
2.4 其他开关
3. 小结
本文主要分析nginx主程序。
nginx主程序main()实现文件:./src/core/nginx.c。.表示nginx-1.0.4代码目录,本文为/usr/src/nginx-1.0.4。
nginx启动过程如下。
简要的函数调用图如下。具体的还是需要阅读源代码。图的自动生成,可参考<用Graphviz可视化函数调用-使用开源软件来简化复杂调用结构>。
00353: ngx_cycle = cycle; /* cycle是调用ngx_init_cycle()的返回值,而调用该函数的参数也是ngx_cycle */ 00354: 00355: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); 00356: 00357: if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) { /* ccf->master=-1 */ 00358: ngx_process = NGX_PROCESS_MASTER; 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)完成初始化的。
具体可参考<nginx源码分析—core模块callback>。
(2)ngx_process
ngx_process是全局变量,定义如下。
//./src/os/unix/ngx_process_cycle.c ngx_uint_t ngx_process; ngx_pid_t ngx_pid; ngx_uint_t ngx_threaded;
其在ngx_init_cycle()中没有被初始化,故其初值为0。
(3)ngx_prefix
static u_char *ngx_prefix; /* nginx工作目录,默认为/usr/local/nginx/ */ static u_char *ngx_conf_file; /* 配置文件 */ 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
关于这一点,可从以下命令结果看出端倪。
# ./nginx -h nginx: nginx version: nginx/1.0.4 nginx: Usage: nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives] Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: /usr/local/nginx/) -c filename : set configuration file (default: conf/nginx.conf) -g directives : set global directives out of configuration file
因此,main()函数返回前调用ngx_master_process_cycle()函数进入多进程(master/worker)工作模式。如下。
00401: if (ngx_process == NGX_PROCESS_SINGLE) { /* 单进程 */ 00402: ngx_single_process_cycle(cycle); 00403: 00404: } else { /* 多进程 */ 00405: ngx_master_process_cycle(cycle); 00406: }具体请参考<nginx源码分析—master/worker进程启动>。
看源代码时,会注意到有些宏(宏全部大写,中间用下划线隔开,这是nginx代码规范。实际上,绝大多数系统均采用此规范)找不到定义,例如NGX_PREFIX、NGX_CONF_PREFIX、NGX_CONF_PATH等。
实际上,这些宏定义由configure程序进行自动配置时生成。配置时会自动生成ngx_auto_config.h文件(如果你用source insight阅读源代码,需要将该文件加入工程),如下。
./objs/ngx_auto_config.h(此处列出其中一部分常用的宏,未按顺序)
#ifndef NGX_COMPILER #define NGX_COMPILER "gcc 4.6.1 20110908 (Red Hat 4.6.1-9) (GCC) " #endif #ifndef NGX_PCRE #define NGX_PCRE 1 #endif #ifndef NGX_PREFIX #define NGX_PREFIX "/usr/local/nginx/" #endif #ifndef NGX_CONF_PREFIX #define NGX_CONF_PREFIX "conf/" #endif #ifndef NGX_CONF_PATH #define NGX_CONF_PATH "conf/nginx.conf" #endif #ifndef NGX_PID_PATH #define NGX_PID_PATH "logs/nginx.pid" #endif #ifndef NGX_LOCK_PATH #define NGX_LOCK_PATH "logs/nginx.lock" #ifndef NGX_ERROR_LOG_PATH #define NGX_ERROR_LOG_PATH "logs/error.log" #endif #ifndef NGX_HTTP_LOG_PATH #define NGX_HTTP_LOG_PATH "logs/access.log" #endif #ifndef NGX_HTTP_CLIENT_TEMP_PATH #define NGX_HTTP_CLIENT_TEMP_PATH "client_body_temp" #endif #ifndef NGX_HTTP_PROXY_TEMP_PATH #define NGX_HTTP_PROXY_TEMP_PATH "proxy_temp" #endif
还有一些开关,如NGX_FREEBSD, NGX_PCRE,NGX_OPENSSL等,这些宏也在configure过程中自动配置。nginx启动时会根据这些宏是否定义调用相应的函数。此处非本文重点,不再赘述。
以上3个宏分别调用相应函数进行debug的初始化、正则表达式初始化和SSL的初始化。如下。(代码未按顺序)
#if (NGX_FREEBSD) ngx_debug_init(); #endif #if (NGX_PCRE) ngx_regex_init(); #endif #if (NGX_OPENSSL) ngx_ssl_init(log); #endif
本文简单分析nginx的启动过程,后文继续分析其中的ngx_init_cycle()和master/worker工作模型。
http://www.tbdata.org/archives/1092
http://www.w3.org/TR/PNG (CRC相关)
Nginx代码研究计划 (RainX1982)
nginx源码分析—模块及其初始化 (阿波)
nginx源码分析—内存池结构ngx_pool_t及内存管理 (阿波)
nginx源码分析—数组结构ngx_array_t (阿波)
nginx源码分析—链表结构ngx_list_t (阿波)
nginx源码分析—队列结构ngx_queue_t (阿波)
nginx源码分析—模块及其初始化 (阿波)
nginx源码分析—内存池结构ngx_pool_t及内存管理 (阿波)
nginx源码分析—数组结构ngx_array_t (阿波)
nginx源码分析—链表结构ngx_list_t (阿波)
nginx源码分析—队列结构ngx_queue_t (阿波)
nginx源码分析—hash结构ngx_hash_t(v1.0.4) (阿波)