我有一个嵌入式 Linux 设备,它通过串行通信协议与另一个“主”设备接口。主设备会定期将其日期传递给从设备,因为稍后从设备会将需要准确时间戳的信息返回给主设备。但是,Linux 的“日期”命令仅将系统日期设置为一秒以内。这对我们的用途来说是不够的。
有人知道如何将 Linux 机器的时间设置为比 1 秒更精确吗?
我有一个嵌入式 Linux 设备,它通过串行通信协议与另一个“主”设备接口。主设备会定期将其日期传递给从设备,因为稍后从设备会将需要准确时间戳的信息返回给主设备。但是,Linux 的“日期”命令仅将系统日期设置为一秒以内。这对我们的用途来说是不够的。
有人知道如何将 Linux 机器的时间设置为比 1 秒更精确吗?
其他答案中给出的settimeofday(2)
方法有一个严重的问题:它完全按照您所说的去做。:)
直接立即更改系统时间的问题在于,如果调整为负数,它会混淆获取更改前后时间的程序。也就是说,他们可以感知时间倒退。
解决这个问题的方法adjtime(3)
是简单且可移植,或者adjtimex(2)
复杂、功能强大且特定于 Linux。这两个调用都使用复杂的算法在一段时间内缓慢调整系统时间,仅向前,直到实现所需的更改。
顺便说一句,你确定你不是在这里重新发明轮子吗?我建议您阅读 Julien Ridoux 和 Darryl Veitch 的 ACM 队列论文《互联网上的鲁棒时序原理》。您正在研究嵌入式系统,所以我预计图 5 中的铃声会让您不寒而栗。你能说“阻尼振荡器”吗?adjtime()
并adjtimex()
使用这个有问题的算法,所以在某种意义上我反对我自己上面的建议,但米尔斯算法仍然比步进调整非算法好。如果您选择实施 RADclock,那就更好了。
系统调用采用settimeofday()
并使用微秒精度。您必须编写一个简短的程序才能使用它,但这很简单。
struct timeval tv;
tv .tv_sec = (some time_t value)
tv .tv_usec = (the number of microseconds after the second)
int rc = settimeofday (&tv, NULL);
if (rc)
errormessage ("error %d setting system time", errno);
可以使用settimeofday(2)
系统调用;接口支持微秒级分辨率。
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
可以使用clock_settime(2)
系统调用;接口提供多个时钟,接口支持纳秒级分辨率。
#include <time.h>
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec
*tp);
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
CLOCK_REALTIME
System-wide real-time clock. Setting this clock
requires appropriate privileges.
CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time
since some unspecified starting point.
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
Similar to CLOCK_MONOTONIC, but provides access to a
raw hardware-based time that is not subject to NTP
adjustments.
CLOCK_PROCESS_CPUTIME_ID
High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
Thread-specific CPU-time clock.
这个接口提供了clock_getres(2)
调用的精确性,它可以准确地告诉你分辨率是什么——仅仅因为接口接受纳秒并不意味着它实际上可以支持纳秒分辨率。(我有一个模糊的记忆,20 ns 大约是许多系统的极限,但没有参考支持这一点。)
如果您在串行链路上运行支持 IP 的网络协议(例如,哦,PPP),您可以在“主”主机上运行 ntpd,然后在嵌入式设备上使用 ntpd 或 ntpdate 同步时间. NTP 会照顾你。