nginx源码学习(五)
2017-04-08 14:11
274 查看
我们接着上篇文章来讲讲ngx_get_options函数。
这个函数就在nginx.c文件中,我们来看看。
参数argc,argv我们在前面的文章中都已经提到了,在这里我们看ngx_get_options里面的for循环。它的作用就是把所有的运行时参数循环一遍,判断是不是合法。例如 nginx -s stop,nginx -s reload等,如果你只输入nginx 或者 nginx -s,则会报错。如果是nginx -h或者-?则是请求帮助信息。nginx -v则是输出版本信息。
好的,我们看main方法里面接下来的函数ngx_show_version_info。同样在nginx.c文件中找到该函数。
这个函数就不多说了,当ngx_show_help = 1的时候就输出帮助信息。
接下来,ngx_time_init()。
看函数名字也知道是初始化时间。ngx_time_init () at src/core/ngx_times.c:65,我们到ngx_times.c里面看看。
前面几行很简单,初始化不同缓存时间长度。nginx获取当前时间是通过gettimeofday函数获取,gettimeofday是C库提供的函数(不是系统调用),它封装了内核里的sys_gettimeofday系统调用。为避免每次都调用OS的gettimeofday,nginx采用时间缓存,每个worker进程都能自行维护。为控制并发访问,每次更新时间缓存前需申请锁,而读时间缓存无须加锁。为避免分裂读,即某worker进程读时间缓存过程中接受中断请求,期间时间缓存被其他worker更新,导致前后读取时间不一致。nginx引入时间缓存数组(共64个成员),每次都更新数组中的下一个元素。
我们重点看看ngx_time_update。
ngx_trylock(&ngx_time_lock),更新缓存前需获取ngx_time_lock。
ngx_gettimeofday(&tv),获取系统时间。
sec = tv.tv_sec;
msec = tv.tv_usec / 1000;
ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
tp = &cached_time[slot]; –读当前时间缓存
如果缓存的时间秒=当前时间秒,直接更新当前slot元素的msec并返回,否则更新下一个slot数组元素。
if (tp->sec == sec) {
tp->msec = msec;
ngx_unlock(&ngx_time_lock);
return;
}
if (slot == NGX_TIME_SLOTS - 1) {
slot = 0;
} else {
slot++;
}
tp = &cached_time[slot];
tp->sec = sec;
tp->msec = msec;
ngx_gmtime(sec, &gmt);
p0 = &cached_http_time[slot][0];
(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);
ngx_sprintf读取所有参数并调用ngx_vslprintf,将后续参数以第二个参数的格式复制到P0开始的内存区,即给cached_http_time[slot]赋值。
后面的cached_err_log_time[slot] & cached_http_log_time[slot] & cached_http_log_iso8601[slot] & cached_syslog_time[slot]也一样。
我们来看看ngx_memory_barrier(),禁止编译器对后面的语句优化。它的作用实际上还是和防止读操作混乱有关,它告诉编译器不要将其后面的语句进行优化,不要打乱其执行顺序。目的是保证缓存时间一致性。
关于时间初始化就到这里,这里面还有很多的细节,这里不进行深入讨论。大家可以自己去了解。
这个函数就在nginx.c文件中,我们来看看。
参数argc,argv我们在前面的文章中都已经提到了,在这里我们看ngx_get_options里面的for循环。它的作用就是把所有的运行时参数循环一遍,判断是不是合法。例如 nginx -s stop,nginx -s reload等,如果你只输入nginx 或者 nginx -s,则会报错。如果是nginx -h或者-?则是请求帮助信息。nginx -v则是输出版本信息。
好的,我们看main方法里面接下来的函数ngx_show_version_info。同样在nginx.c文件中找到该函数。
这个函数就不多说了,当ngx_show_help = 1的时候就输出帮助信息。
接下来,ngx_time_init()。
看函数名字也知道是初始化时间。ngx_time_init () at src/core/ngx_times.c:65,我们到ngx_times.c里面看看。
前面几行很简单,初始化不同缓存时间长度。nginx获取当前时间是通过gettimeofday函数获取,gettimeofday是C库提供的函数(不是系统调用),它封装了内核里的sys_gettimeofday系统调用。为避免每次都调用OS的gettimeofday,nginx采用时间缓存,每个worker进程都能自行维护。为控制并发访问,每次更新时间缓存前需申请锁,而读时间缓存无须加锁。为避免分裂读,即某worker进程读时间缓存过程中接受中断请求,期间时间缓存被其他worker更新,导致前后读取时间不一致。nginx引入时间缓存数组(共64个成员),每次都更新数组中的下一个元素。
我们重点看看ngx_time_update。
ngx_trylock(&ngx_time_lock),更新缓存前需获取ngx_time_lock。
ngx_gettimeofday(&tv),获取系统时间。
sec = tv.tv_sec;
msec = tv.tv_usec / 1000;
ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
tp = &cached_time[slot]; –读当前时间缓存
如果缓存的时间秒=当前时间秒,直接更新当前slot元素的msec并返回,否则更新下一个slot数组元素。
if (tp->sec == sec) {
tp->msec = msec;
ngx_unlock(&ngx_time_lock);
return;
}
if (slot == NGX_TIME_SLOTS - 1) {
slot = 0;
} else {
slot++;
}
tp = &cached_time[slot];
tp->sec = sec;
tp->msec = msec;
ngx_gmtime(sec, &gmt);
p0 = &cached_http_time[slot][0];
(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);
ngx_sprintf读取所有参数并调用ngx_vslprintf,将后续参数以第二个参数的格式复制到P0开始的内存区,即给cached_http_time[slot]赋值。
后面的cached_err_log_time[slot] & cached_http_log_time[slot] & cached_http_log_iso8601[slot] & cached_syslog_time[slot]也一样。
我们来看看ngx_memory_barrier(),禁止编译器对后面的语句优化。它的作用实际上还是和防止读操作混乱有关,它告诉编译器不要将其后面的语句进行优化,不要打乱其执行顺序。目的是保证缓存时间一致性。
关于时间初始化就到这里,这里面还有很多的细节,这里不进行深入讨论。大家可以自己去了解。
相关文章推荐
- nginx 源码学习笔记(一)——初识nginx helloworld模块
- nginx 源码学习笔记(二)——nginx精粹-模块
- nginx 源码学习笔记(十)——基本容器——ngx_hash
- Nginx源码学习(2)----ngx_string
- nginx 源码学习笔记(十二)——基本容器——ngx_buf
- [转载]Nginx源码学习之编译、构建与安装(cygwin环境)
- nginx 源码学习笔记(十四)—— 全局变量ngx_cycle
- nginx 源码学习笔记(九)——基本容器——queue
- nginx 源码学习笔记(九)——基本容器——queue
- nginx 源码学习笔记(十三)——文件读写和配置文件读取
- nginx 源码学习笔记(三)——nginx精粹-模块
- nginx 源码学习笔记(五)——nginx精粹-模块
- nginx 源码学习笔记(五)——nginx精粹-模块
- nginx 源码学习笔记(十)——基本容器——ngx_hash
- nginx 源码学习笔记(七)——内存分配相关源码分析
- nginx 源码学习笔记(二)——nginx精粹-模块
- nginx 源码学习笔记(四)——nginx精粹-模块
- nginx 源码学习笔记(六)——nginx基本数据结构
- nginx 源码学习笔记(十一)——基本容器——ngx_list
- nginx 源码学习笔记(十四)—— 全局变量ngx_cycle