Nginx的启动过程
主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程。
涉及到的基本函数
源码:
Code
Nginx的启动包括了很多的初始化和处理函数。这些函数相对来说,有一部分非常复杂,暂且从简单开始,从整体上对Ngixnd的启动有一个了解,方便日后的分析与学习。
主要函数:
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结构体,这个结构体用来存储所有的连接,具体如下:
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;
}
参考
http://blog.xiuwz.com/2011/11/29/nginx-pcre-conflict/
http://blog.csdn.net/liuhongxiangm/article/details/8107613
http://blog.csdn.net/livelylittlefish/article/details/7243718
Nginx的启动过程的更多相关文章
- 【Nginx】启动过程
		
从应用程序的启动过程中main功能开始跟踪. 解析命令行參数并保存到ngx_cycle_t结构体中,在ngx_process_options函数中将保存配置文件路径. 调用ngx_add_inheri ...
 - Nginx安装启动过程报错libpcre.so.1 cannot open shared object file: No such file or directory
		
具体报错信息如下: nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: ...
 - Nginx学习笔记(六) 源码分析&启动过程
		
Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...
 - 基于多进程和基于多线程服务器的优缺点及nginx服务器的启动过程
		
基于多进程服务器的优点: 1.由操作系统进行调度,运行比较稳定强壮 2.能够方便地通过操作系统进行监控和管理 例如对每个进程的内存变化状况,甚至某个进程处理什么web请求进行监控.同时可以通过给进程发 ...
 - Nginx源码研究一:NGINX模块启动
		
Nginx 是一个轻量级,但是高性能的 HTTP 和 代理 服务器,也是一个 IMAP/POP3/SMTP代理服务器. 它的第一个版本0.1.0是由俄罗斯的工程师Igor Sysoev与2004年10 ...
 - client和nginx简易交互过程
		
# client和nginx简易交互过程- step1:client发起http请求- step2:dns服务器解析域名得到主机ip- step3:默认端口为80,通过ip+port建立tcp/ip链 ...
 - laravel启动过程简单解析
		
:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px ...
 - 初始nginx(启动运行) 使用nginx做一个简单的静态资源服务器
		
第一次接触nginx的时候,那时候公司还是用的一些不知名的小技术,后来公司发展问题,重新招了人,然后接触到nginx,公司 使用nginx用来做代理服务器,所有请求 都先经过nginx服务器,然后交由 ...
 - linux如何查看nginx是否启动
		
Nginx是一个高性能的反向代理服务器,现在一般作为我们网站或其他Web服务的第一层代理,用户在浏览器请求首先经过的就是Nginx服务. 如果Nginx服务没有启动或异常结束,将会影响Web服务的正常 ...
 
随机推荐
- 【poj2528】Mayor's posters
			
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 64939 Accepted: 18770 ...
 - [洛谷P2417]课程
			
题目链接: 点我 题目分析: 二分图最大匹配裸题,跑完匈牙利判断\(ans\)是否等于教室数即可 多组数据请注意初始化. 代码: #include<bits/stdc++.h> #defi ...
 - BFS HDOJ 1242 Rescue
			
题目传送门 题意:从r走到a,遇到x多走一步,问最小走到a的步数 分析:因为r有多个,反过来想从a走到某个r的最小步数,简单的BFS.我对这题有特殊的感情,去年刚来集训队时肉鸽推荐了这题,当时什么都不 ...
 - [转]EntityFramework之领域驱动设计实践
			
本文转自:http://www.cnblogs.com/daxnet/archive/2010/11/02/1867392.html Entity Framework之领域驱动设计实践 EntityF ...
 - 使用css3 制作switch开关
			
使用css3来实现switch开关的效果: html代码: <!--switch开关--><div class="switch-btn"> <inpu ...
 - 【学习笔记】彻底理解JS中的this
			
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
 - Bean with name 'xxxService' has been injected into other beans [xxxServiceA,xxxServiceB]  in its raw version as part of a circular reference, but has eventually been wrapped
			
启动项目,通过@Autowired注入对象,出现循环依赖,导致项目启动失败,具体报错信息如下: Exception encountered during context initialization ...
 - js实现跨域的方法
			
由于同源策略的限制,XMLHttpRequest只允许请求当前源(包含域名.协议.端口)的资源. json与jsonp的区别: JSON是一种数据交换格式,而JSONP是一种依靠开发人员创造出的 ...
 - vim下ctrl + s 僵死问题的解决
			
vim下ctrl + s 僵死问题的解决 vim 使用vim习惯性手残Ctrl+S ,解决方法 : Ctrl + Q 就能恢复了
 - BZOJ 2157: 旅游 (2017.7.21 6:30-2017.7.21 15:38  今日第一题。。)
			
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1754 Solved: 765 Description Ray 乐忠于旅游,这次他来到了T 城.T ...