主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程。
涉及到的基本函数
源码:
View Code
Nginx的启动包括了很多的初始化和处理函数。这些函数相对来说,有一部分非常复杂,暂且从简单开始,从整体上对Ngixnd的启动有一个了解,方便日后的分析与学习。
主要函数:
//完成socket的继承
static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
//对参数选项进行处理 static ngx_int_t ngx_get_options(int argc, char *const *argv);
//初始化ngx_cycle内的部分内容 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
//命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv全局的变量中 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
//创建模块的配置信息 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
//初始化配置信息 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf); static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//设置优先级 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//设置CPU亲和性 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//设置worker进程 static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
Nginx启动的主要流程
下图为Nginx的启动时函数的调用过程,其中大部分都是为了Nginx启动的初始化部分。从错误处理、参数设置、时间设置等方面进行初始化,并注册了我们需要的模块,最后根据信号选择单任务模式还是master-worker模式。
流程图:
初始化
主函数在开始对系统错误、参数、时间、系统变量、日志等进行了初始化。
//初始化系统中错误编号对应的含义 ngx_strerror_init(); //对参数选项进行处理 ngx_get_options(argc, argv); //时间初始化 ngx_time_init(); //重置pcre内存管理的接口 ngx_regex_init(); //日志初始化 ngx_log_init(ngx_prefix);
//创建内存池
ngx_create_pool(1024, log);
//保存变量
ngx_save_argv();
//初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param
ngx_process_options();
//初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
ngx_os_init();
//初始化CRC表(后续的CRC校验通过查表进行,效率高)
ngx_crc32_table_init();
主要工作
初始化完成后,需要先调用ngx_add_inherited_sockets函数继承socket,并储存在Listening数组中,在运行时候进行监听。之后就可以调用ngx_init_cycle来初始化ngx_cycle结构体,这个结构体用来存储所有的连接,具体如下:
struct ngx_cycle_s { void ****conf_ctx;//配置上下文数组(含所有模块) ngx_pool_t *pool;//内存池 ngx_log_t *log;//日志 ngx_log_t new_log; ngx_connection_t **files;//连接文件 ngx_connection_t *free_connections;//空闲连接 ngx_uint_t free_connection_n;//空闲连接数 ngx_queue_t reusable_connections_queue;////再利用连接队列 ngx_array_t listening;//监听数组 ngx_array_t paths;//路径数组 ngx_list_t open_files;//打开文件链表 ngx_list_t shared_memory;//共享内存链表 ngx_uint_t connection_n;//连接个数 ngx_uint_t files_n;//打开文件个数 ngx_connection_t *connections; ngx_event_t *read_events;//读事件 ngx_event_t *write_events;//写事件 ngx_cycle_t *old_cycle; ngx_str_t conf_file;//配置文件 ngx_str_t conf_param;//配置参数 ngx_str_t conf_prefix;//配置前缀 ngx_str_t prefix;//前缀 ngx_str_t lock_file;//锁文件 ngx_str_t hostname;
调用ngx_init_signals来注册信号。
//信号种类
#define NGX_PROCESS_SINGLE 0 #define NGX_PROCESS_MASTER 1 #define NGX_PROCESS_SIGNALLER 2 #define NGX_PROCESS_WORKER 3 #define NGX_PROCESS_HELPER 4
在进入处理之前,还要调用ngx_create_pidfile来记录进程id。最后,根据接收到的信号,来判断调用ngx_single_process_cycle还是ngx_master_process_cycle(master-worker模式)。
if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); }
其中,守护进程函数为ngx_daemon,位于src/os/unix/Ngx_daemon.c
//daemon
ngx_int_t ngx_daemon(ngx_log_t *log) { int fd; switch (fork()) { case -1: ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed"); return NGX_ERROR; case 0: breakdefault: exit(0); } ngx_pid = ngx_getpid();//取得进程识别码 if (setsid() == -1) { //子进程将重新获得一个新的会话(session)id ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed"); return NGX_ERROR; } umask(0); fd = open("/dev/null", O_RDWR); if (fd == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(\"/dev/null\") failed"); return NGX_ERROR; } if (dup2(fd, STDIN_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed"); return NGX_ERROR; } if (dup2(fd, STDOUT_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed"); return NGX_ERROR; } #if 0 if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return NGX_ERROR; } #endif if (fd > STDERR_FILENO) { if (close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } } return NGX_OK; }
本文转自cococo点点博客园博客,原文链接:http://www.cnblogs.com/coder2012/p/3166658.html,如需转载请自行联系原作者