zoukankan      html  css  js  c++  java
  • 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
     
     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://www.4os.org/index.php/2010/11/25/nginx%E5%90%AF%E5%8A%A8%E5%88%9D%E5%A7%8B%E5%8C%96%E8%BF%87%E7%A8%8B%E8%BD%AC%E8%BD%BD/

    http://blog.csdn.net/livelylittlefish/article/details/7243718

  • 相关阅读:
    [2010山东ACM省赛] Balloons(搜索)
    [2010山东ACM省赛] Greatest Number(数的组合+二分搜索)
    [ACM] hdu 1213 How Many Tables(并查集)
    C Shuffle Cards
    快速读入输出模板
    J Distance to Work
    E Sort String
    H Diff-prime Pairs
    A PACM Team
    区间 (interval)
  • 原文地址:https://www.cnblogs.com/xialiaoliao0911/p/7524017.html
Copyright © 2011-2022 走看看