ADJTIMEX - Linux手册页

时间:2019-08-20 18:00:57  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-06-09

名称

adjtimex,clock_adjtime,ntp_adjtime-调整内核时钟

语法

#include <sys/timex.h>

int adjtimex(struct timex *buf);

int clock_adjtime(clockid_t clk_id, struct timex *buf);

int ntp_adjtime(struct timex *buf);

说明

Linux使用David L.Mills的时钟调整算法(请参阅RFC 5905)。系统调用adjtimex()读取并可选地为此算法设置调整参数。它使用指向timex结构的指针,从(选定的)字段值更新内核参数,并返回使用当前内核值更新的相同结构。该结构声明如下:

struct timex {
    int  modes;      /* Mode selector */
    long offset;     /* Time offset; nanoseconds, if STA_NANO
                        status flag is set, otherwise
                        microseconds */
    long freq;       /* Frequency offset; see NOTES for units */
    long maxerror;   /* Maximum error (microseconds) */
    long esterror;   /* Estimated error (microseconds) */
    int  status;     /* Clock command/status */
    long constant;   /* PLL (phase-locked loop) time constant */
    long precision;  /* Clock precision
                        (microseconds, read-only) */
    long tolerance;  /* Clock frequency tolerance (read-only);
                        see NOTES for units */
    struct timeval time;
                     /* Current time (read-only, except for
                        ADJ_SETOFFSET); upon return, time.tv_usec
                        contains nanoseconds, if STA_NANO status
                        flag is set, otherwise microseconds */
    long tick;       /* Microseconds between clock ticks */
    long ppsfreq;    /* PPS (pulse per second) frequency
                        (read-only); see NOTES for units */
    long jitter;     /* PPS jitter (read-only); nanoseconds, if
                        STA_NANO status flag is set, otherwise
                        microseconds */
    int  shift;      /* PPS interval duration
                        (seconds, read-only) */
    long stabil;     /* PPS stability (read-only);
                        see NOTES for units */
    long jitcnt;     /* PPS count of jitter limit exceeded
                        events (read-only) */
    long calcnt;     /* PPS count of calibration intervals
                        (read-only) */
    long errcnt;     /* PPS count of calibration errors
                        (read-only) */
    long stbcnt;     /* PPS count of stability limit exceeded
                        events (read-only) */
    int tai;         /* TAI offset, as set by previous ADJ_TAI
                        operation (seconds, read-only,
                        since Linux 2.6.26) */
    /* Further padding bytes to allow for future expansion */
};

模式字段确定要设置的参数(如果有)。 (如本页稍后所述,用于ntp_adjtime()的常量是等效的,但名称有所不同。)它是一个位掩码,其中包含以下任一或多个零位或多个位的组合:

ADJ_OFFSET
设置与buf.offset的时间偏移。从Linux 2.6.26开始,提供的值被限制在范围内(-0.5s,+ 0.5s)。在较早的内核中,如果提供的值超出范围,则会发生EINVAL错误。
ADJ_FREQUENCY
设置buf.freq的频率偏移。从Linux 2.6.26开始,提供的值被限制在范围内(-32768000,+32768000)。在较早的内核中,如果提供的值超出范围,则会发生EINVAL错误。
ADJ_MAXERROR
从buf.maxerror设置最大时间错误。
ADJ_ESTERROR
从buf.esterror设置估计的时间错误。
ADJ_STATUS
从buf.status设置时钟状态位。这些位的描述在下面提供。
ADJ_TIMECONST
从buf.constant设置PLL时间常数。如果STA_NANO状态标志(请参见下文)被清除,则内核在该值上加4。
ADJ_SETOFFSET(since Linux 2.6.39)
将buf.time添加到当前时间。如果buf.status包含ADJ_NANO标志,则buf.time.tv_usec解释为纳秒级值;否则,将其解释为微秒。
buf.time的值是其两个字段的总和,但是字段buf.time.tv_usec必须始终为非负数。以下示例显示了如何以纳秒分辨率对时间间隔进行标准化。
while (buf.time.tv_usec < 0) {
    buf.time.tv_sec  -= 1;
    buf.time.tv_usec += 1000000000;
}
ADJ_MICRO(since Linux 2.6.26)
选择微秒分辨率。
ADJ_NANO(since Linux 2.6.26)
选择纳秒分辨率。仅应指定ADJ_MICRO和ADJ_NANO之一。
ADJ_TAI(since Linux 2.6.26)
设置buf.constant的TAI(原子国际时间)偏移量。
ADJ_TAI不应与ADJ_TIMECONST结合使用,因为后者的模式也使用buf.constant字段。
有关TAI的完整说明以及TAI和UTC之间的区别,请参阅BIPM。
ADJ_TICK
从buf.tick设置刻度值。

或者,可以将模式指定为以下(多位掩码)值之一,在这种情况下,不应在模式中指定其他位:

ADJ_OFFSET_SINGLESHOT
老式的adjtime(3):(逐渐地)通过buf.offset中指定的值来调整时间,该值指定以微秒为单位的调整。
ADJ_OFFSET_SS_READ(functional since Linux 2.6.28)
返回(以buf.offset为单位)在较早的ADJ_OFFSET_SINGLESHOT操作之后要调整的剩余时间量。此功能已在Linux 2.6.24中添加,但是直到Linux 2.6.28才可以正常使用。

普通用户的模式限制为0或ADJ_OFFSET_SS_READ。只有超级用户可以设置任何参数。

buf.status字段是位掩码,用于设置和/或检索与NTP实现相关的状态位。掩码中的某些位既可读又可设置,而其他则为只读。

STA_PLL(read-write)
通过ADJ_OFFSET启用锁相环(PLL)更新。
STA_PPSFREQ(read-write)
启用PPS(每秒脉冲)频率规则。
STA_PPSTIME(read-write)
启用PPS时间纪律。
STA_FLL(read-write)
选择锁频环(FLL)模式。
STA_INS(read-write)
在UTC日期的最后一秒之后插入一个leap秒,从而将日期的最后一分钟延长一秒。只要此标志保持置位状态,每天都会插入ap秒。
STA_DEL(read-write)
在UTC的最后一秒删除a秒。只要此标志保持设置,每天都会发生秒删除。
STA_UNSYNC(read-write)
时钟不同步。
STA_FREQHOLD(read-write)
保持频率。通常,通过ADJ_OFFSET进行的调整也会导致衰减的频率调整。因此,一次调用就可以校正当前偏移,但是随着在同一方向上重复进行偏移,将累积少量的频率调整以固定长期偏斜。
该标志防止在校正ADJ_OFFSET值时进行小的频率调整。
STA_PPSSIGNAL(read-only)
存在有效的PPS(每秒脉冲)信号。
STA_PPSJITTER(read-only)
超出了PPS信号抖动。
STA_PPSWANDER(read-only)
PPS信号漂移超出范围。
STA_PPSERROR(read-only)
PPS信号校准错误。
STA_CLOCKERR(read-only)
时钟硬件故障。
STA_NANO(read-only; since Linux 2.6.26)
分辨率(0 =微秒,1 =纳秒)。通过ADJ_NANO设置,通过ADJ_MICRO清除。
STA_MODE(since Linux 2.6.26)
模式(0 =锁相环,1 =频率锁相环)。
STA_CLK(read-only; since Linux 2.6.26)
时钟源(0 = A,1 = B);当前未使用。

设置只读状态位的尝试将被静默忽略。

clock_adjtime ()

clock_adjtime()系统调用(在Linux 2.6.39中添加了)的行为类似于adjtimex(),但需要一个额外的clk_id参数来指定要对其操作的特定时钟。

ntp_adjtime ()

ntp_adjtime()库函数(在NTP"内核应用程序API",KAPI中进行了描述)是一种可移植的接口,用于执行与adjtimex()相同的任务。除了以下几点,它与adjtimex()相同:

*
模式中使用的常量以" MOD_"而不是" ADJ_"为前缀,并且具有以下相同的后缀(因此,MOD_OFFSET,MOD_FREQUENCY等),但以下几点除外。
*
MOD_CLKA是ADJ_OFFSET_SINGLESHOT的同义词。
*
MOD_CLKB是ADJ_TICK的同义词。
*
不是ADJ_OFFSET_SS_READ的同义词,KAPI中没有对此进行描述。

返回值

成功时,adjtimex()和ntp_adjtime()返回时钟状态;即,以下值之一:

TIME_OK
时钟已同步,没有leap秒调整待定。
TIME_INS
表示将在UTC日结束时添加a秒。
TIME_DEL
表示a秒将在UTC日结束时删除。
TIME_OOP
正在插入a秒。
TIME_WAIT
leap秒的插入或删除操作已完成。该值将一直返回,直到下一个ADJ_STATUS操作清除STA_INS和STA_DEL标志为止。
TIME_ERROR
The system clock is not synchronized to a reliable server. This value is returned when any of the following holds true:
*
设置STA_UNSYNC或STA_CLOCKERR。
*
STA_PPSSIGNAL是清除的,并且已设置STA_PPSFREQ或STA_PPSTIME。
*
STA_PPSTIME和STA_PPSJITTER均已设置。
*
设置STA_PPSFREQ并设置STA_PPSWANDER或STA_PPSJITTER。
符号名称TIME_BAD是TIME_ERROR的同义词,为向后兼容而提供。

请注意,从Linux 3.4开始,该调用是异步操作的,并且返回值通常不会反映该调用本身引起的状态更改。

失败时,这些调用将返回-1并设置errno。

错误说明

EFAULT
buf不指向可写内存。
EINVAL(kernels before Linux 2.6.26)
试图将buf.freq设置为超出范围(-33554432,+33554432)的值。
EINVAL(kernels before Linux 2.6.26)
试图将buf.offset设置为允许范围之外的值。在Linux 2.0之前的内核中,允许的范围是(-131072,+131072)。从Linux 2.0开始,允许的范围是(-512000,+512000)。
EINVAL
试图将buf.status设置为上述值以外的值。
EINVAL
出于以下两个原因之一,赋予clock_adjtime()的clk_id无效。 System-V样式硬编码的正时钟ID值超出范围,或者动态clk_id没有引用时钟对象的有效实例。有关动态时钟的讨论,请参见clock_gettime(2)。
EINVAL
尝试将buf.tick设置为900000 / HZ到1100000 / HZ之外的值,其中HZ是系统计时器中断频率。
ENODEV
由动态clk_id表示的可热插拔设备(例如USB)在其字符设备打开后已消失。有关动态时钟的讨论,请参见clock_gettime(2)。
EOPNOTSUPP
给定的clk_id不支持调整。
EPERM
buf.modes既不是0也不是ADJ_OFFSET_SS_READ,并且调用者没有足够的特权。在Linux下,需要CAP_SYS_TIME功能。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
ntp_adjtime()Thread safetyMT-Safe

遵循规范

POSIX.1中没有描述这些接口。

adjtimex()和clock_adjtime()是特定于Linux的,不应在打算移植的程序中使用。

NTP守护程序的首选API是ntp_adjtime()。

备注

在struct timex中,freq,ppsfreq和stabil是ppm(百万分之一),具有16位小数部分,这意味着这些字段之一中的值1实际上表示2 ^ -16 ppm,而2 ^ 16 = 65536是1 ppm。输入值(对于频率)和输出值均属于这种情况。

STA_INS和STA_DEL触发的leap秒处理由内核在计时器上下文中完成。因此,插入或删除the秒需要一秒。

另外参见

clock_gettime(2),clock_settime(2),settimeofday(2),adjtime(3),ntp_gettime(3),capabilities(7),time(7),adjtimex(8),hwclock(8)

NTP"内核应用程序接口"

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/