继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_HAVE_GETTIMEZONE)
//ngx_gettimezone获得世界时间和当地时间的时间差(以妙计)
tp->gmtoff = ngx_gettimezone();
//tp->gmtoff是相差的分钟数,所以应该乘以60获得秒数,考虑到时区的误差,ngx_gmttime将time_t转换成tm数据类型
ngx_gmtime(sec + tp->gmtoff * 60, &tm);
#elif (NGX_HAVE_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函数,根据是否需要更新当前缓存时间,如果需要则将时间格式转化成多种。
未完,待续...