nginx main流程分析



int ngx_cdecl
main(int argc, char *const * argv)
{
    ngx_int_t         i;
    ngx_log_t        * log;
    ngx_cycle_t      * cycle, init_cycle ;
    ngx_core_conf_t  * ccf;


    /*
                第一个函数ngx_debug_init(),这个函数主要是作为初始化debug用的,nginx中的debug,主要是对内存池分配管理方面的debug,因为作为一个应用程序,最容易出现bug的地方也是内存管理这块。在Linux版本中,这个函数只是一个空定义(src/os/unix/ngx_linux_config.h)。
                #define ngx_debug_init()
                */
    ngx_debug_init();

    /*
                 *我们来到程序的第208行,ngx_strerror_init(),该函数的定义在文件src/os/unix/ngx_errno.c中。
     *该函数主要初始化系统中错误编号对应的含义,这样初始化中进行对应的好处是,当出现错误,
     *不用再去调用strerror()函数来获取错误原因,而直接可以根据错误编号找到对应的错误原因,
     *可以提高运行时的执行效率。从这里可以看到,nginx开发者的别有用心,对于微小的性能提升也毫不放过。 */
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    //获得运行时选项
    if (ngx_get_options( argc, argv ) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_write_stderr( "nginx version: " NGINX_VER NGX_LINEFEED );

        if (ngx_show_help) {
            ngx_write_stderr(
                "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
                             "[-p prefix] [-g directives]" NGX_LINEFEED
                             NGX_LINEFEED
                "Options:" NGX_LINEFEED
                "  -?,-h         : this help" NGX_LINEFEED
                "  -v            : show version and exit" NGX_LINEFEED
                "  -V            : show version and configure options then exit"
                                   NGX_LINEFEED
                "  -t            : test configuration and exit" NGX_LINEFEED
                "  -q            : suppress non-error messages "
                                   "during configuration testing" NGX_LINEFEED
                "  -s signal     : send signal to a master process: "
                                   "stop, quit, reopen, reload" NGX_LINEFEED
#ifdef NGX_PREFIX
                "  -p prefix     : set prefix path (default: "
                                   NGX_PREFIX ")" NGX_LINEFEED
#else
                "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
#endif
                "  -c filename   : set configuration file (default: "
                                   NGX_CONF_PATH ")" NGX_LINEFEED
                "  -g directives : set global directives out of configuration "
                                   "file" NGX_LINEFEED NGX_LINEFEED
                );
        }

        if (ngx_show_configure) {
            ngx_write_stderr(
#ifdef NGX_COMPILER
                "built by " NGX_COMPILER NGX_LINEFEED
#endif
#if (NGX_SSL)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
                "TLS SNI support enabled" NGX_LINEFEED
#else
                "TLS SNI support disabled" NGX_LINEFEED
#endif
#endif
                "configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    //初始化系统时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

    //初始化日志信息
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init( log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */


    /*
    ngx_string.h 第86行
    #define ngx_memzero(buf, n)       (void) memset(buf, 0, n)
    ngx_cycle_s 机构体:ngx_cycle.h 第37行
    */
    ngx_memzero(& init_cycle, sizeof (ngx_cycle_t));

    //开始初始化ngx_cycle_s *init_cycle对象
    init_cycle. log = log ;

    ngx_cycle = & init_cycle;

    // 为ngx_cycle 创建内存池 ,ngx_pool我们在另一篇博客中再讲
    init_cycle. pool = ngx_create_pool(1024, log );
    if (init_cycle. pool == NULL ) {
        return 1;
    }

    // 保存进程参数到init_cycle中
    if (ngx_save_argv(& init_cycle, argc , argv) != NGX_OK) {
        return 1;
    }

    // 处理进程参数
    if (ngx_process_options(& init_cycle) != NGX_OK) {
        return 1;
    }


    // 获取系统配置信息 (分页大小,CPU 个数,CPU 制造商,文件符最大数等)  
    if (ngx_os_init( log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    // 初始化循环冗余检验表,验证接收数据
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    //通过环境变量NGINX完成socket的继承,这些继承来的socket会放到init_cycyle的listening数组中。
    if (ngx_add_inherited_sockets(& init_cycle) != NGX_OK) {
        return 1;
    }

    ngx_max_module = 0;
   
     /**
     * nginx把所有模块(ngx_module_t)存放到ngx_modules数组中,这个数组在nginx源码路
     * 径的objs/ngx_modules.c中,是在运行configure脚本后生成的。index属性就是该模块
     * 在ngx_modules数组中的下标。同时nginx把所有的core module的配置结构存放到ngx_cycle的
     * conf_ctx数组中,index也是该模块的配置结构在ngx_cycle->conf_ctx数组中的下标。
     **/
    for (i = 0; ngx_modules[ i]; i ++) {
        ngx_modules[ i]->index = ngx_max_module++;
    }

    // 初始化init cycle 变量,这是个牛逼的结构 
    cycle = ngx_init_cycle(& init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed" ,
                           init_cycle.conf_file .data);
        }

        return 1;
    }

    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful" ,
                           cycle->conf_file .data);
        }

        return 0;
    }

    if (ngx_signal) {
        return ngx_signal_process(cycle , ngx_signal);
    }

    ngx_os_status( cycle->log );

    ngx_cycle = cycle;

    // 获取core module 的配置指针  
    ccf = (ngx_core_conf_t *) ngx_get_conf( cycle->conf_ctx , ngx_core_module);

    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        ngx_process = NGX_PROCESS_MASTER;
    }

#if !(NGX_WIN32)
    //初始化信号
    if (ngx_init_signals( cycle->log ) != NGX_OK) {
        return 1;
    }

    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle ->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    if (ngx_create_pidfile(& ccf->pid , cycle-> log) != NGX_OK) {
        return 1;
    }

    if (cycle-> log->file ->fd != ngx_stderr) {

        if (ngx_set_stderr(cycle ->log-> file->fd ) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log , ngx_errno,
                          ngx_set_stderr_n " failed");
            return 1;
        }
    }

    //检查log文件句柄
    if (log-> file->fd != ngx_stderr) {
        if (ngx_close_file(log ->file-> fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log , ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle( cycle);

    } else {
        ngx_master_process_cycle( cycle);
    }

    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值