Nginx学习笔记(六) 源码分析&启动过程

简介:

主要介绍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,如需转载请自行联系原作者
相关文章
|
17天前
|
应用服务中间件 Linux 网络安全
CentOS 7.4源码编译nginx1.12 并且隐藏nginx的版本
CentOS 7.4源码编译nginx1.12 并且隐藏nginx的版本
15 0
|
3月前
|
算法 应用服务中间件 nginx
NGINX下的红黑树源码详解(附 流程图和GIF)(1)
之前博主稍微讲解了下红黑树的原理,那么在这篇博客博主想要把红黑树讲的更加的透彻,以便于更多的人了解红黑树 (本博客会更加详细的介绍之前的博客没介绍到的,所以各位看官不同再回去翻看博主之前那篇红黑树的原理讲解了。)
39 3
|
2月前
|
tengine Rust 负载均衡
反向代理学习笔记(一) Nginx与反向代理绪论
反向代理学习笔记(一) Nginx与反向代理绪论
|
3月前
|
应用服务中间件 nginx
Nginx源码阅读:共享内存ngx_shm_t和它的组织方式ngx_shm_zone_t、ngx_list_t
Nginx源码阅读:共享内存ngx_shm_t和它的组织方式ngx_shm_zone_t、ngx_list_t
24 0
|
3月前
|
应用服务中间件 nginx
Nginx源码阅读:ngx_list_t 链表
Nginx源码阅读:ngx_list_t 链表
52 0
|
3月前
|
存储 应用服务中间件 nginx
Nginx模块开发:模块结构的源码阅读以及过滤器(Filter)模块的实现
Nginx模块开发:模块结构的源码阅读以及过滤器(Filter)模块的实现
65 0
|
3月前
|
算法 应用服务中间件 nginx
NGINX下的红黑树源码详解(附 流程图和GIF)(2)
那我们就接着之前的gif继续吧 涉及到的 3/4、5情况(精简版) 情况3:变化前[当前结点为4节点]: 当前节点的父节点是红色且祖父节点的另一个子节点(叔叔节点)是红色。
22 2
|
8月前
|
前端开发 应用服务中间件 nginx
前端学习笔记202305学习笔记第二十三天-nginx项目部署500情况
前端学习笔记202305学习笔记第二十三天-nginx项目部署500情况
47 0
|
4月前
|
应用服务中间件 Linux 网络安全
源码方式安装nginx及其依赖并设置服务开机启动
源码方式安装nginx及其依赖并设置服务开机启动
115 0
|
7月前
|
缓存 负载均衡 应用服务中间件