读nginx main函数【总纲】

来源:互联网 发布:linux usermod ag 编辑:程序博客网 时间:2024/05/20 19:48

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下的大小为:


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;       /* nginx工作目录,默认为/usr/local/nginx/ */  
  2. static u_char      *ngx_conf_file;    /* 配置文件 */  
  3. static u_char      *ngx_conf_params;  /* nginx指令 */  




step 12

    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }
初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等;

ngx_int_tngx_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: 关于系统软限制和硬限制的查看方式如下


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++;
    }
初始化每个moduleindex,并计算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()进入进程循环;

0 0
原创粉丝点击