ntpdate如何更新时间?

时间:2012-11-06 17:29:18

标签: time linux-kernel ntp

我在strace命令上使用ntpdate调用adjtimex来调整时间。 我明白了:

adjtimex({modes=ADJ_OFFSET|0x8000, offset=-479139, freq=0, maxerror=16000000, esterror=16000000, status=STA_UNSYNC, constant=2, precision=1, tolerance=32768000, time={1352220968, 428418}, tick=10000, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0}) = 5 (TIME_ERROR)

然后我研究了do_adjtimex主函数中adjtimex API的实现。 但是从代码中我看不出ntpdate如何调整时间。

modes=ADJ_OFFSET|0x8000=ADJ_OFFSET|ADJ_ADJTIME

int do_adjtimex(struct timex *txc)
{
    struct timespec ts;
    int result;
/* Validate the data before disabling interrupts */
if (txc->modes & ADJ_ADJTIME) { **<----this is true. modes as ADJ_OFFSET|ADJ_ADJTIME**
    /* singleshot must not be used with any other mode bits */
    if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
        return -EINVAL;
    if (!(txc->modes & ADJ_OFFSET_READONLY) &&
        !capable(CAP_SYS_TIME))
        return -EPERM;
} else {
    .....
}

if (txc->modes & ADJ_SETOFFSET) { **《===this is false**
    .....
}

getnstimeofday(&ts);**《------------just get the walk time**

spin_lock_irq(&ntp_lock);

if (txc->modes & ADJ_ADJTIME) {<----this is true.
    long save_adjust = time_adjust; **<----this is global valu eoffset=-479139**

    if (!(txc->modes & ADJ_OFFSET_READONLY)) {
        /* adjtime() is independent from ntp_adjtime() */
        time_adjust = txc->offset;
        ntp_update_frequency();
    }
    txc->offset = save_adjust;
} else {

    .......
}

result = time_state;    /* mostly `TIME_OK' */ this is 
/* check for errors */
if (is_error_status(time_status)) **<----this is STA_UNSYNC**
    result = TIME_ERROR;

txc->freq      = shift_right((time_freq >> PPM_SCALE_INV_SHIFT) *
                 PPM_SCALE_INV, NTP_SCALE_SHIFT);
txc->maxerror      = time_maxerror;
txc->esterror      = time_esterror;
txc->status    = time_status;
txc->constant      = time_constant;
txc->precision     = 1;
txc->tolerance     = MAXFREQ_SCALED / PPM_SCALE;
txc->tick      = tick_usec;
txc->tai       = time_tai;

/* fill PPS status fields */
pps_fill_timex(txc);

spin_unlock_irq(&ntp_lock);

txc->time.tv_sec = ts.tv_sec;
txc->time.tv_usec = ts.tv_nsec;
if (!(time_status & STA_NANO))
    txc->time.tv_usec /= NSEC_PER_USEC;

notify_cmos_timer(); <---- call sync_cmos_clock.

return result;
}

sync_cmos_clock检查ntp是否已同步。 time_status是STA_UNSYNC。 什么都不做,然后回来。

if (!ntp_synced()) { /*
                      * Not synced, exit, do not restart a timer (if one is
                      * running, let it run out). */
return; }

我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

ntp.c已从kernel/timer.ckernel/time.c

移出

ntp.c内,您会找到对ntp_update_frequency()的调用。

if (!(txc->modes & ADJ_OFFSET_READONLY)) {
   /* adjtime() is independent from ntp_adjtime() */
   time_adjust = txc->offset;
   ntp_update_frequency();
}
txc->offset = save_adjust;

ntp_update_frequency()将更新u64 tick_lengthstatic tick_length_base。 请注意adjtimentp_adjtime的独立性。