Chinaunix首页 | 论坛 | 博客
  • 博客访问: 663100
  • 博文数量: 78
  • 博客积分: 4990
  • 博客等级: 上校
  • 技术积分: 1386
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-13 19:25
文章分类

全部博文(78)

文章存档

2010年(6)

2009年(25)

2008年(47)

我的朋友

分类: LINUX

2010-04-22 17:21:48

在阅读日志模块的时候发现ngx_log_error_core的90~91行:ngx_memcpy(errstr, ngx_cached_err_log_time.data,ngx_cached_err_log_time.len);可以看出在日志所用函数的时间来至于变量ngx_cached_err_log_time,顺便找到该变量在ngx_times.c中定义。先把一个主要的函数代码贴上来,在细细分析一下:
void ngx_time_update(time_t sec, ngx_uint_t msec)
{
    u_char          *p0, *p1, *p2;
    ngx_tm_t         tm, gmt;
    ngx_time_t      *tp;
    struct timeval   tv;

    if (!ngx_trylock(&ngx_time_lock)) {
        return;
    }

    if (sec == 0) {
        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];

    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);

#if (NGX_HAVE_GETTIMEZONE)

    tp->gmtoff = ngx_gettimezone();
    ngx_gmtime(sec + tp->gmtoff * 60, &tm);

#elif (NGX_HAVE_GMTOFF)

    ngx_localtime(sec, &tm);
    tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);

#else

    ngx_localtime(sec, &tm);
    tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst);

#endif


    p1 = &cached_err_log_time[slot][0];

    (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];

    (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));


    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_unlock(&ngx_time_lock);
}
看最后几行代码就可以知道这个函数要想得到什么:ngx_cached_http_time.data = p0;
    ngx_cached_err_log_time.data = p1;
    ngx_cached_http_log_time.data = p2;
好我现在想将函数里面比较细节的几个东西。
ngx_trylock(&ngx_time_lock) 这个函数,没看到ngx_time_lock在什么地方赋值,由于是全局变量,故其值为0;ngx_trylock在ngx_atomic.h中定义为:#define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1)), 而ngx_atomic_cmp_set定义在ngx_gcc_atomic_x86.h中:
static ngx_inline ngx_atomic_uint_t
ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
    ngx_atomic_uint_t set)
{
    u_char  res;

    __asm__ volatile (

         NGX_SMP_LOCK
    "    cmpxchgl  %3, %1;   "
    "    sete      %0;       "

    : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");

    return res;
}
到这里我们要思考一个问题,为什么ngx_time_update这个函数使用ngx_trylock这个函数,我们一步一步来分析。
再来看ngx_atomic_cmp_set这个函数:
1.NGX_SMP_LOCK是当PC是SMP时的“lock”的宏定义。
2.在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。
3.cmpxchgl 指令是比较如果相等并将第二个操作数放到第一个操作数的位置上,%3,%1指第三个和第一个参数。这里指的应当是(×lock)和(set)。
4. sete      %0;“sete” 是一个设置指令,如果zf=1则%0也就是第一个参数res为1,否则为0;
更多要知道嵌入式汇编的的东西我觉得看这篇文章就差不多了:http://blog.csdn.net/zdfonline/archive/2005/03/17/321904.aspx

另外,ngx_time_update函数还调用了ngx_localtime 注意在计算月份和年份时,月份要加1,年份加1900,见代码:
voidngx_localtime(time_t s, ngx_tm_t *tm)
{
#if (NGX_HAVE_LOCALTIME_R)
    (void) localtime_r(&s, tm);

#else
    ngx_tm_t  *t;

    t = localtime(&s);
    *tm = *t;

#endif

    tm->ngx_tm_mon++;
    tm->ngx_tm_year += 1900;
}

阅读(3939) | 评论(0) | 转发(0) |
0

上一篇:ubuntu下mysql安装和使用(1)

下一篇:没有了

给主人留下些什么吧!~~