我在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; }
我错过了什么吗?
答案 0 :(得分:0)
ntp.c已从kernel/timer.c
和kernel/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_length
和static tick_length_base
。
请注意adjtime
和ntp_adjtime
的独立性。