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

nginx之main函数的解读(五)

2014-10-14 10:53 3627 查看
继ngx_get_options之后,接下来的代码是:

if (ngx_show_version) {
	    //ngx_write_stderr 定义在ngx_log.h中的内联函数,想文件中写入信息nginx version
		//NGX_LINEFEED的定义是\x0a,也就是换行
        ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);
       //当输入参数中包含了h时,会展示帮助信息
        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
                );
        }
这段代码的含义很简单,就是如果用户在启动nginx时 输入了 -h的参数的话,则会显示该字符串,提示用户应该输入何种参数,同时参数的含义是什么,接下来时显示配置信息,个人觉得没什么含义

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;
        }
    }
ngx_max_sockets=-1;


现在看下一个函数调用ngx_time_init(),该函数定义在core中的ngx_times.c文件当中

void
ngx_time_init(void)
{ 
    //ngx_cached_err_log_time  ngx_cached_http_time  ngx_cached_http_log_time  ngx_cached_http_log_iso8601是一个ngx_str_t的结构体
    ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1;
    ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
    ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1;
    ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1;
    //ngx_cached_time  是ngx_time_t类型的结构体该结构体的定义是在/src/core/nginx_time.h当中
    ngx_cached_time = &cached_time[0];
    //该函数就在ngx_time.c文件当中
    ngx_time_update();
}
上述各种诸如ngx_cache_err_log_time和ngx_cache_http_time和ngx_cahce_http_log_iso8601等等都是ngx_str_t的结构体变量,而里面之有一个ngx_cache_time,

定义在core中的ngx_times.h文件当中是ngx_time_t类型的结构体

<pre name="code" class="cpp">//时间更新函数
void
ngx_time_update(void)
{
    u_char          *p0, *p1, *p2, *p3;
    //ngx_tm_t是tm的重定义
    ngx_tm_t         tm, gmt;
    time_t           sec;
    ngx_uint_t       msec;
    ngx_time_t      *tp;
    struct timeval   tv;
    //ngx_time_lock是ngx_atomic_t类型的数据,而ngx_atomic_t可以认为是一个无符号整数
    //ngx_trylock该函数在src/os/unix/ngx_atomic.h文件当中
   //该ngx_trylock的操作是要求ngx_time_lock是一个无符号整型,由0变成1成功执行,则为真,否则失败,也就是说该函数只允许一个线程执行,否则容易出现错误
    if (!ngx_trylock(&ngx_time_lock)) {
        return;
    }
   //当前并没有线程执行到此,只有一个线程执行该函数
    //ngx_gettimeofday是gettimeofday的重定义,获得当前系统时间
    ngx_gettimeofday(&tv);
    sec = tv.tv_sec;//秒的数值
    msec = tv.tv_usec / 1000;//毫秒的数值
    //ngx_current_msec是一个无符号整型
    ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;//当前的毫秒的数值
    //cache_time是一个ngx_time_t的数组指针,slot也是一个无符号整型,ngx_time_t类型的结构体该结构体的定义是在/src/core/nginx_time.h当中
   //slot是静态变量初始化成0,这样tp也就是ngx_cache_time
    tp = &cached_time[slot];
    //如果缓存中索引是slot中获取的时间的秒数就是当前系统的秒数,则将将缓存中获取的时间微秒数置成他的千分之一,然后进行ngx_time_lock解锁操作
    if (tp->sec == sec) {
         //进入到这里是否可以表示,当前时间不用更新,
         tp->msec = msec;
	//ngx_unlock是在src/os/unix/ngx_atomic.h文件中他的操作是将ngx_time_lock指向的内存内容置成0
        ngx_unlock(&ngx_time_lock);
        return;
    }
    //执行到这里说明我们需要更新缓存时间
    //如果slot达到索引的最大值,则将slot置成0,否则自增1
    if (slot == NGX_TIME_SLOTS - 1) {
        slot = 0;
    } else {
        slot++;
    }
    //获取缓存时间中的第slot个ngx_time_t结构体
    tp = &cached_time[slot];
    //将该时间结构体的秒数置成当前系统的秒数,微秒数设置成当前微秒数+秒数*1000的数值
    tp->sec = sec;
    tp->msec = msec;
    //ngx_gmtime函数就在src/core/ngx_times.c文件当中
    //该函数的作用是将sec中的秒数换算成年月日 星期等,也就是换成gmt的时间格式
    ngx_gmtime(sec, &gmt);
    //cache_http_time定义在本文件当中,是u_char类型的二维数组,行是NGX_TIME_SLOTS,列则是需要我们指定的时间格式的长度"Mon, 28 Sep 1970 06:00:00 GMT"
    p0 = &cached_http_time[slot][0];
    //这样的话就将cache_http_time格式化成如下类型的时间格式
    (void) ngx_sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT",
                       week[gmt.ngx_tm_wday], gmt.ngx_tm_mday,
                       months[gmt.ngx_tm_mon - 1], gmt.ngx_tm_year,
                       gmt.ngx_tm_hour, gmt.ngx_tm_min, gmt.ngx_tm_sec);

#if (NGX_H***E_GETTIMEZONE)
    //ngx_gettimezone获得世界时间和当地时间的时间差(以妙计)
    tp->gmtoff = ngx_gettimezone();
   //tp->gmtoff是相差的分钟数,所以应该乘以60获得秒数,考虑到时区的误差,ngx_gmttime将time_t转换成tm数据类型
    ngx_gmtime(sec + tp->gmtoff * 60, &tm);

#elif (NGX_H***E_GMTOFF)
    //ngx_local_time是放在src/os/unix/ngx_time.c文件当中的
    ngx_localtime(sec, &tm);
    cached_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);
    tp->gmtoff = cached_gmtoff;

#else

    ngx_localtime(sec, &tm);
	//ngx_tm_isdst如果是1表示使用夏令时,否则不适用
    cached_gmtoff = ngx_timezone(tm.ngx_tm_isdst);
    tp->gmtoff = cached_gmtoff;

#endif

//到这里得到了我们最终需要的时间:tm,然后呢,根据需要,将tm转化成我们需要的格式即可
    p1 = &cached_err_log_time[slot][0];
    //时间格式"1970/09/28 12:00:00"
    (void) ngx_sprintf(p1, "%4d/%02d/%02d %02d:%02d:%02d",
                       tm.ngx_tm_year, tm.ngx_tm_mon,
                       tm.ngx_tm_mday, tm.ngx_tm_hour,
                       tm.ngx_tm_min, tm.ngx_tm_sec);

    //
    p2 = &cached_http_log_time[slot][0];
   //时间格式"28/Sep/1970:12:00:00 +0600"
    (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d",
                       tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1],
                       tm.ngx_tm_year, tm.ngx_tm_hour,
                       tm.ngx_tm_min, tm.ngx_tm_sec,
                       tp->gmtoff < 0 ? '-' : '+',
                       ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));

    p3 = &cached_http_log_iso8601[slot][0];
    //时间格式"1970-09-28T12:00:00+06:00"
    (void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
                       tm.ngx_tm_year, tm.ngx_tm_mon,
                       tm.ngx_tm_mday, tm.ngx_tm_hour,
                       tm.ngx_tm_min, tm.ngx_tm_sec,
                       tp->gmtoff < 0 ? '-' : '+',
                       ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));

    ngx_memory_barrier();//阻止多核处理器进行指令优化
    ngx_cached_time = tp;
    ngx_cached_http_time.data = p0;
    ngx_cached_err_log_time.data = p1;
    ngx_cached_http_log_time.data = p2;
    ngx_cached_http_log_iso8601.data = p3;
   //ngx_unlock是在src/os/unix/ngx_atomic.h文件中他的操作是将ngx_time_lock指向的内存内容置成0
    ngx_unlock(&ngx_time_lock);
}
当然cahce_time就是ngx_time_t结构体的数组



里面最后调用了ngx_time_update函数,根据是否需要更新当前缓存时间,如果需要则将时间格式转化成多种。

未完,待续...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: