您的位置:首页 > 运维架构 > Nginx

读nginx main函数【总纲】

2014-01-27 13:07 190 查看

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()函数中进行的初始化。

static u_char      *ngx_prefix;       /* nginx工作目录,默认为/usr/local/nginx/ */  

static u_char      *ngx_conf_file;    /* 配置文件 */  

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



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()进入进程循环;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nginx main 启动