Решение 2038 года для встроенного Linux (32-разрядная версия)?

Как правильно обрабатывать время в коде C для 32-разрядной встроенной Linux (ARMLinux), чтобы гарантировать, что код продолжает работать правильно после 03:14:07 UTC 19 января 2038 года (когда подписанный 32-разрядный time_t переполняется) ? Учитывая, что time_t имеет 32-разрядную подпись в системе, которую я должен использовать, какие есть альтернативы?

Значительное количество поисков в Google не выявило ничего практического. Кажется, все предполагают, что к тому времени мы все будем использовать 64-битные ОС, но это явно не так для встраиваемых систем.

В системе, которую я должен использовать, __kernel_time_t определяется как long. Что, по-видимому, означает, что для 64-битного времени нет ядра. Версия uClibc 0.9.29.

Я не могу поверить, что я единственный с этой проблемой, и я не хочу изобретать велосипед.


person Ian Goldby    schedule 26.01.2016    source источник
comment
Хотя я согласен, что это хороший вопрос, он может быть слишком широким для SO. Вы искали LKML или отправили запрос?   -  person too honest for this site    schedule 26.01.2016
comment
@Olaf: я читал о том, что делают авторы ядра Linux, но все это вращается вокруг 64-битных систем. Я не думаю, что этот вопрос слишком широк; честно говоря, я сомневаюсь, что существует так много разных способов сделать это, и вполне возможно, что ответ будет таким: в настоящее время просто нет универсального решения для встраиваемых систем.   -  person Ian Goldby    schedule 26.01.2016
comment
Пройдет 20+ лет   -  person n. 1.8e9-where's-my-share m.    schedule 26.01.2016
comment
@н.м. В мире встраиваемых систем 20 лет — это совсем немного. Одной из систем, над которыми я работаю, более 35 лет.   -  person Ian Goldby    schedule 26.01.2016
comment
Единственная система, о которой я знаю, которая в настоящее время является time_t перспективной на 32-битных машинах, - это OpenBSD.   -  person Art    schedule 26.01.2016
comment
@n.m.: Удивительно, но есть области применения, которые не выпускают новое устройство каждый год. Для бытовой техники подумайте, например. стиральные машины (не самые дешевые, конечно) и т.д.   -  person too honest for this site    schedule 26.01.2016
comment
Вы имеете в виду физическую установку 35-летней давности или программное обеспечение 35-летней давности? Первый придется заменить/обновить до 2038 года, несмотря ни на что. Для последнего размер слова целевого процессора не имеет значения. Используйте комбинацию ОС/компилятор/стандартная библиотека, которая поддерживает 64-битный time_t (или time64_t). Если вы не выберете комбинацию, сообщите о проблеме в письменной форме тому, кто за нее отвечает, и двигайтесь дальше. Вы не можете решить все их проблемы.   -  person n. 1.8e9-where's-my-share m.    schedule 26.01.2016
comment
@н.м. Посмотрите, какое аппаратное и программное обеспечение используется для управления ядерными реакторами в Канаде. Это может вас удивить. И вас может удивить, что они планируют поддерживать их работу до 2050 года. 35 лет — это немного.   -  person Art    schedule 26.01.2016
comment
@Art Им больше (ядерной) энергии. Я надеюсь, что этим системам на самом деле не нужно синхронизироваться с реальными часами, так что эпоха может быть определена для них произвольно. Просто установите их часы на ноль где-то до 2038 года.   -  person n. 1.8e9-where's-my-share m.    schedule 26.01.2016
comment
@н.м. Я бы посчитал умным решением установку часов на ноль, я в них не верю. Если это не делается регулярно. Я подозреваю, что большинство проблем с time_t будут типа if (timeout_time ‹= current_time) handle_timeout();, которые у нас уже были, когда time_t было 2 ^ 31 - 10 ^ 9 и люди (Oracle был одним) использовал миллиард секунд как тайм-аут в невероятно далеком будущем. Никакие хитрые уловки не решат эту проблему.   -  person Art    schedule 26.01.2016
comment
@Art if (timeout_time <= current_time) handle_timeout(); Для всех подобных вещей следует использовать монотонные часы, а не time() или gettimeofday() или что-то в этом роде. Конечно, монотонные часы тоже могут зацикливаться, если вы не перезагрузитесь. И, конечно же, сбрасывать эпоху очень некрасиво и может сломать систему. Хотел бы я иметь серебряную пулю, но ее нет.   -  person n. 1.8e9-where's-my-share m.    schedule 26.01.2016
comment
@н.м. Нужно, но люди очень часто этого не делают. Кроме того, лучшие источники монотонных часов возвращают временную спецификацию, которая в соответствии с POSIX имеет тип time_t для tv_sec, а также иногда (но не всегда) просто основана на обычном времени, но без корректировок. Ваш лучший выбор — монотонные часы, которые возвращают время безотказной работы (популярный выбор), но многие системы отслеживают время безотказной работы только как смещение от времени настенных часов (что довольно отстало), что может снова привести к проблемам с time_t.   -  person Art    schedule 26.01.2016
comment
Привет из 2021! Linux 5.6 и выше готовы к работе после 2038 года на 32-разрядных системах: lkml.org/lkml/2020/1/29/355?anz=web   -  person Emile Cormier    schedule 09.04.2021


Ответы (3)


Нет серебряных пуль, уловок или умных решений. Либо используйте 64-битную time_t операционную систему, либо не используйте time_t и любые зависящие от нее средства ОС (включая файловые системы, таймеры, половину сети и т. д.), либо планируйте обновление программного обеспечения в ближайшие 20 лет.

Есть как минимум две unix-подобные системы с 64-битной time_t на 32-битных машинах: OpenBSD и NetBSD. У OpenBSD было несколько докладов, объясняющих причины этого: .html

person Art    schedule 26.01.2016
comment
Я отметил это как ответ просто потому, что нашим окончательным решением было пока жить с 32-битным временем и беспокоиться о проблеме позже. Не лучшее решение IMO, но компонент, над которым я работаю, не единственный затронутый. - person Ian Goldby; 27.01.2016
comment
Поскольку ARMLinux, похоже, основан на NetBSD, вы можете сохранить 32-битную версию. Но проверьте это в источнике. Неудивительно, что 2038 год — это далекое будущее. это меньше, чем 18 лет с этого момента. - person theking2; 09.08.2020
comment
Привет из 2021! Linux 5.6 и выше готовы к работе после 2038 года на 32-разрядных системах: lkml.org/lkml/2020/1/29/355?anz=web - person Emile Cormier; 09.04.2021

Процедуры преобразования времени «просто» должны использовать 2038-01-19:03:14:07Z в качестве основы для времени эпохи Unix, если метка времени ниже определенного значения.

т.е. если ваша система стала продуктивной в 2010-01-01, вы можете предположить, что никакая метка времени, которая не переполняется, не ниже 1262300400 (это время эпохи unix для этой даты).

Если встречается более низкая метка времени, считайте, что она переполнена, и используйте 2038-01-19:03:14:07Z в качестве базового времени. Сравнения также должны быть приняты во внимание.

Не чистое решение, но выполнимое с умеренными усилиями. Лучше переключитесь на 64-битные временные метки (кстати, для этого абсолютно не нужна 64-битная система).

person Ctx    schedule 26.01.2016
comment
Это ужасный подход. В моей системе Linux есть довольно много файлов с отметками времени в 1999 году или около того. Кроме того, когда вы извлекаете архивы, полученные откуда-то еще (например, из обновления пакета), все mtimes могут быть испорчены. - person fuz; 26.01.2016
comment
@FUZxxl Я согласен;) Но мы говорим о встроенных здесь, влияние может быть управляемым - person Ctx; 26.01.2016
comment
Влияние неправдоподобных меток времени из будущего может быть фатальным. Например, он полностью сбрасывает make или программы резервного копирования, которые работают на основе метки времени. - person fuz; 26.01.2016
comment
@FUZxxl: Я определенно не хочу путешествовать в этот день: самолеты, поезда и автомобили... к тому времени все они могут быть самостоятельными, но, вероятно, не застрахованы от жуков Y2G. - person chqrlie; 26.01.2016
comment
Это довольно изобретательно, но, возможно, слишком умно. Это, безусловно, будет интересным сюрпризом для тех, кому может понадобиться обслуживать систему после вас. Является ли это предзнаменованием будущего поста SO вашей заменой? - person Zhro; 26.01.2016

Я предполагаю, что ABI вашей встроенной системы определяет long как 32 бита.

Тип time_t не обязательно должен быть подписан. Не могли бы вы сделать это unsigned long и купить себе и своим потомкам дополнительные 68 лет спокойствия? Изменение этого потребует перекомпиляции ядра, библиотеки C и всех программ и библиотек, использующих time_t... не для слабонервных! С тем же успехом вы могли бы определить его как long long, но это изменило бы многие макеты структур и стало еще более сложным.

person chqrlie    schedule 26.01.2016
comment
Если вам надоело перекомпилировать каждый двоичный файл во всей системе, почему бы не обновиться!? - person cat; 26.01.2016
comment
@cat: хорошее замечание! Если OP имеет достаточный контроль над стеком системного программного обеспечения, у него есть несколько вариантов предотвращения проблемы, причем обновление является гораздо лучшим решением, чем исправление с помощью типов ядра, если он этого не делает, мало что можно сделать. - person chqrlie; 26.01.2016