Установите время Linux с точностью до миллисекунды

У меня есть встроенное устройство Linux, которое взаимодействует с другим "главным" устройством по протоколу последовательной связи. Периодически ведущее устройство передает свою дату подчиненному устройству, потому что позднее ведомое устройство будет возвращать ведущему устройству информацию, которая должна иметь точную временную метку. Однако команда Linux "date" устанавливает системную дату только с точностью до секунды. Этого недостаточно для нашего использования.

Кто-нибудь знает, как установить время Linux-машины более точно, чем 1 секунда?

4 ответа

settimeofday(2) Метод, приведенный в других ответах, имеет серьезную проблему: он делает именно то, что вы говорите, что хотите.:)

Проблема с непосредственным изменением системного времени, мгновенно, заключается в том, что это может запутать программы, которые получают время дня до и после изменения, если корректировка была отрицательной. То есть они могут воспринимать время, чтобы вернуться назад.

Исправление для этого adjtime(3) который прост и портативен, или adjtimex(2) который сложен, мощен и специфичен для Linux. Оба этих вызова используют сложные алгоритмы, чтобы медленно регулировать системное время в течение некоторого периода, только вперед, до тех пор, пока не будет достигнуто желаемое изменение.

Кстати, вы уверены, что не изобретаете колесо здесь? Я рекомендую вам прочитать статью ACM Queue of Julien Ridoux и Darryl Veitch " Принципы надежной синхронизации по Интернету". Вы работаете над встраиваемыми системами, поэтому я ожидаю, что звуки на рисунке 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 нс - это пределы многих систем, но нет ссылок, подтверждающих это.)

Если вы используете сетевой протокол с поддержкой IP через последовательный канал (например, ooh, PPP), вы можете просто запустить ntpd на "главном" хосте, а затем синхронизировать время, используя ntpd или ntpdate на встроенном устройстве., NTP позаботится о вас.

Другие вопросы по тегам