天天看点

读nginx main函数【总纲】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 1

ngx_debug_init(); //linux下为空函数

step 2

if (ngx_strerror_init() != NGX_OK) {

    return 1; }

NGX_SYS_NERR,定义在/home/nginx-1.4.4/objs/ngx_auto_config.h, configure的时候自动生成,生成的办法待研究

debian下的大小为:

读nginx main函数【总纲】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

static ngx_str_t  *ngx_sys_errlist;//指向一个NGX_SYS_NERR * sizeof(ngx_str_t);大小的内存

//遍历NGX_SYS_NERR这么多个err     for (err = 0; err < NGX_SYS_NERR; err++) {

        msg = strerror(err);   //strerror()用来翻译错误码的宏定义的意思

        len = ngx_strlen(msg);

        p = malloc(len);

        if (p == NULL) {

            goto failed;

        }

        ngx_memcpy(p, msg, len); //开一块内存,将错误码对应的意思拷贝进去 //将以错误码为下标的元素赋值,之后通过错误码可以直接和错误意思对应

        ngx_sys_errlist[err].len = len;

        ngx_sys_errlist[err].data = p;

    }

step 3

    if (ngx_get_options(argc, argv) != NGX_OK) {

        return 1;

    }

初始化各环境变量(全局变量)

step 4

ngx_time_init();

服务器时间的初始化,不明觉厉,需要看到后面再回来研究。

step 5

#if (NGX_PCRE)

    ngx_regex_init();

#endif

正则初始化, 不明觉厉,需要看到后面再回来研究。

step 6

ngx_pid = ngx_getpid();

取得目前进程的进程pid

step 7

    log = ngx_log_init(ngx_prefix);

    if (log == NULL) {

        return 1;

    }

日志初始化,日志模块后面会单独开辟一章来分析,先留空。

step 8

#if (NGX_OPENSSL)

    ngx_ssl_init(log);

#endif

SSL初始化

step 9

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));

    init_cycle.log = log;

    ngx_cycle = &init_cycle;

    init_cycle.pool = ngx_create_pool(1024, log);

    if (init_cycle.pool == NULL) {

        return 1;

    }

初始化一个类型为ngx_cycle_t的局部变量,初始化该结构的log指针,pool指针

step 10

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {

        return 1;

    }

把main函数的argc, argv存在ngx_os_argv、ngx_argc、ngx_argv这三个全局变量里面, 不明觉厉,日后再说。

step 11

    if (ngx_process_options(&init_cycle) != NGX_OK) {

        return 1;

    }

初始化 ngx_cycle结构体 的 prefix, conf_prefix, conf_file, conf_param 等字段

初始化这些结构体变量是根据ngx_prefix、ngx_conf_file、ngx_conf_params等全局变量来的,而这些全局变量是在ngx_get_options()函数中进行的初始化。

  1. static u_char      *ngx_prefix;         
  2. static u_char      *ngx_conf_file;      
  3. static u_char      *ngx_conf_params;    
读nginx main函数【总纲】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22
读nginx main函数【总纲】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 12

    if (ngx_os_init(log) != NGX_OK) {

        return 1;

    }

初始化系统相关变量,如内存页面大小 ngx_pagesize , ngx_cacheline_size , 最大连接数 ngx_max_sockets 等;

ngx_int_t
ngx_os_init(ngx_log_t *log)
{
    ngx_uint_t  n;

#if (NGX_HAVE_OS_SPECIFIC_INIT)
    if (ngx_os_specific_init(log) != NGX_OK) {
        return NGX_ERROR;
    }
#endif

    ngx_init_setproctitle(log);

	//返回一分页的大小, 单位为字节(byte). 此为系统的分页大小, 不一定会和硬件分页大小相同.
	//在intel x86上为4096 bytes
    ngx_pagesize = getpagesize();

	//设置cpu cacheline大小,该宏定义在./ngx_auto_config.h:#define NGX_CPU_CACHE_LINE  32
	//http://blog.csdn.net/zdl1016/article/details/8882092
    ngx_cacheline_size = NGX_CPU_CACHE_LINE;

	//每次循环,n折半
    for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }

#if (NGX_HAVE_SC_NPROCESSORS_ONLN)
    if (ngx_ncpu == 0) {
        ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
    }
#endif

    if (ngx_ncpu < 1) {
        ngx_ncpu = 1;
    }

	//不明觉厉,根据CPU类型设置ngx_cacheline_size的大小
    ngx_cpuinfo();

	//RLIMIT_NOFILE参数,获取进程可以打开的最多文件数,APUE II P164.之7.11节
    if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
        ngx_log_error(NGX_LOG_ALERT, log, errno,
                      "getrlimit(RLIMIT_NOFILE) failed)");
        return NGX_ERROR;
    }

	//记录能打开的最大文件数到ngx_max_sockets全局变量
    ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur;

#if (NGX_HAVE_INHERITED_NONBLOCK || NGX_HAVE_ACCEPT4)
    ngx_inherited_nonblocking = 1;
#else
    ngx_inherited_nonblocking = 0;
#endif

	//设置random函数的种子
    srandom(ngx_time());

    return NGX_OK;
}
           

btw: 关于系统软限制和硬限制的查看方式如下

读nginx main函数【总纲】step 3step 4step 5step 6step 7step 8step 9step 10step 11step 12step 13step 14step 15step 16step 17step 18step 19step 20step 21step 22

step 13

    if (ngx_crc32_table_init() != NGX_OK) {

        return 1;

    }

不明觉厉,需要专门分析。

step 14

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {

        return 1;

    }

不明觉厉,需要专门分析。

step 15

    ngx_max_module = 0;

    for (i = 0; ngx_modules[i]; i++) {

        ngx_modules[i]->index = ngx_max_module++;

    }

初始化每个 module 的 index ,并计算module的最大值 ngx_max_module

step 16

    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;

    }

对 ngx_cycle 结构进行初始化, 重要,需要细看。

step 17

    if (ngx_signal) {

        return ngx_signal_process(cycle, ngx_signal);

    }

若有信号,则处理信号。

step 18

    ngx_cycle = cycle;

    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;

    }

step 19

    if (ngx_init_signals(cycle->log) != NGX_OK) {

        return 1;

    }

该函数根据signals来初始化信号。

signals[ ]的定义在src/os/unix/ngx_process.c中,定义了各种信号的处理函数。

step 20

    if (!ngx_inherited && ccf->daemon) {

        if (ngx_daemon(cycle->log) != NGX_OK) {

            return 1;

        }

        ngx_daemonized = 1;

    }

    if (ngx_inherited) {

        ngx_daemonized = 1;

    }

没看懂,待分析

step 21

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

        return 1;

    }

创建进程记录文件

step 22

    if (ngx_process == NGX_PROCESS_SINGLE) {

        ngx_single_process_cycle(cycle);

    } else {

        ngx_master_process_cycle(cycle);

    }

进入进程主循环;

  • 若为NGX_PROCESS_SINGLE=1模式,则调用ngx_single_process_cycle()进入进程循环;
  • 否则为master-worker模式,调用ngx_master_process_cycle()进入进程循环;

继续阅读