Примерно в 2000 году Apple написала пресс-релиз о том, что каждый Mac с 1984 года избежит проблемы Y2K и сможет обрабатывать даты за следующие несколько тысяч лет.
Хорошей новостью является то, что с момента своего появления в 1984 году компьютеры Macintosh имели возможность переходить на 2000 год. Фактически, Mac OS и большинство приложений Mac могут правильно обрабатывать внутренне сгенерированные даты вплоть до 29 940 года.
Это заявление было сделано, когда Mac OS 9 была самой последней операционной системой.
С тех пор OS X (теперь называемая macOS) является доминирующей операционной системой, производной от Unix. Означает ли это, что любая версия уязвима к проблеме 2038 года , проблеме, сравнимой с проблемой Y2K, затрагивающей Unix-подобные системы? Или заявление Apple о совместимости с 29 940 годом все еще остается верным?
Все версии до OS X 10.6 "Snow Leopard" имеют проблему 2038 года. Большинство установок 10.6 и все установки 10.7 «Lion» устранили основную причину проблемы. Это почти исчезло, но ошибка 2038 года может сохраниться в нескольких приложениях.
Мой старый PowerPC Mac работает под управлением OS X 10.4.11 «Tiger». Я зашел в «Дата и время» в «Системных настройках» и попытался ввести дату после 2038 года, но она сбрасывала дату на 31 декабря 2037 года. Он знает, что в 2038 году что-то не так.
OS X получена из Unix посредством BSD. Приложения для OS X используют системные вызовы BSD для таких вещей, как открытие файлов и подключение к Интернету. BSD имеет долгую историю, и некоторые из ее системных вызовов появились в 1980-х годах. Одним из его системных вызовов является gettimeofday()
, который впервые появился в 4.1cBSD. Калифорнийский университет в Беркли выпустил 4.1cBSD в 1982 году , более чем за полвека до 2038 года. Время от gettimeofday()
— целое число типа time_t
. Он считает секунды, где ноль — это эпоха Unix 1970-01-01 00:00:00 UTC.
В моем старом PowerPC Mac time_t
это 32-битное целое число со знаком. Это вызывает проблему 2038 года. 32-битный знак со знаком time_t
имеет диапазон от -2147483648 до 2147483647. Он может содержать только время от 1901-12-13 20:45:52 UTC до 2038-01-19 03:14:07 UTC. Когда это переполнится, gettimeofday()
дата перевернется с понедельника, 19 января 2038 года, на пятницу, 13 декабря 1901 года.
Исправление заключается в переходе с 32-битной time_t
на 64-битную версию time_t
. Для OS X этот переход произошел вместе с другим переходом от 32-битных указателей к 64-битным указателям, но для 64-битных указателей требуется 64-битный процессор. Apple предоставила 64-битную версию только time_t
для 64-битных процессоров. 32-битные процессоры могут работать с 64-битными time_t
, но Apple никогда не предоставляла эту функцию.
Компиляторы Apple поддерживают 64-битные целые числа на 32-битных процессорах, начиная с OS X 10.0 «Cheetah», когда time_t
были 32-битные и off_t
64-битные. В Unix и BSD off_t
это размер файла или всего диска. 32-разрядная версия off_t
ограничит OS X дисками до 2 ГБ. Apple определила их off_t
как 64-битные, поэтому OS X работала с большими дисками. Apple определила time_t
32-битную версию в 10.0, поэтому переход на 64-битную версию time_t
должен был произойти позже.
Для моего старого PowerPC Mac файл заголовка <ppc/_types.h>
определяется __darwin_time_t
как long
. Для Intel Mac заголовок <i386/_types.h>
делает то же самое. В OS X long
имеет тот же размер, что и указатель. Итак, когда указатели стали 64-битными, они long
также стали 64-битными и time_t
также стали 64-битными, что устранило основную причину проблемы 2038 года.
В Руководстве Apple по переходу на 64-разрядную версию говорится: «До OS X версии 10.6 все приложения, поставляемые с операционной системой, были 32-разрядными приложениями. Начиная с версии 10.6, приложения, поставляемые с операционной системой, обычно являются 64-разрядными приложениями. ." Я знаю из Википедии , что для версии 10.6 требовался процессор Intel, а для версии 10.7 — 64-разрядный процессор Intel. Mac под управлением 10.6 на 32-разрядном процессоре Intel должен иметь 32-разрядные приложения. Я пришел к выводу, что большинство компьютеров Mac под управлением 10.6 и все Mac под управлением 10.7 имеют 64-разрядные приложения с 64-разрядными указателями и 64-разрядными файлами time_t
. Apple выпустила версию 10.7 в 2011 году, задолго до января 2038 года.
В 64-битной версии time_t
ошибка 2038 года почти устранена, но она может сохраниться в некоторых приложениях. Старые 32-разрядные приложения могут по-прежнему работать в более новых системах. Кроме того, 64-разрядные приложения могут содержать ошибки кодирования или устаревший дизайн, что приводит к преобразованию 64-разрядных приложений time_t
в 32-разрядные. Это проблема всех систем, не только macOS.
Есть еще время Маха. Ядро OS X смешивает BSD с Mach. Большинство приложений получают время от BSD с помощью gettimeofday()
, но есть способ обойти BSD и получить время от Mach. Это сложнее: программа будет звонить mach_host_self()
, чтобы получить порт хоста, затем host_get_clock_service()
получить CALENDAR_CLOCK
и, наконец, clock_get_time()
.
На моем старом Mac под управлением 10.4 «Тигр» <mach/clock_types.h>
время объявляется как unsigned int
(внутри struct mach_timespec
). Это 32-разрядное целое число без знака в диапазоне от 0 до 4294967295, то есть от 1970-01-01 00:00:00 UTC до 2106-02-07 06:28:15 UTC. Это заменит проблему 2038 года на проблему 2106 года. Он не может достичь 29 940 года.
Я подозреваю, что host_get_clock_service()
это устарело с 10.0 «Cheetah», потому что Apple предоставила более быстрые способы узнать время. Это были BSD gettimeofday()
для календарного времени и Apple mach_absolute_time()
для монотонного времени. Предпочтение gettimeofday()
поставить проблему 2038, а не 2106.
Ну, а что касается El Capitan 10.11.6, то ответить на него не так просто, как с помощью Perl-скрипта.
Если мы попробуем это
macmladen@buk $ touch -t 205012121212 my
macmladen@buk $ ls -al
total 104
drwx------ 7 root root 4096 Dec 25 13:42 .
drwxr-xr-x 23 root root 4096 Dec 4 17:06 ..
-rw-r--r-- 1 root root 0 Dec 12 2050 my
Таким образом, это доказывает , что macOS на самом низком системном уровне защищена от ошибки Y2038. А значит система как таковая не даст сбоев и будет работать корректно.
Однако на прикладном уровне это не всегда так.
При попытке установить дату на 2040 год Системные настройки Дата и время ответили, установив ее на 01.01.2038 (вам придется снять флажок автоматически)
Это означает, что от приложения зависит, как оно отреагирует на ошибку Y2038.
Эль-Капитан не подвержен:
#!/usr/bin/perl
use POSIX;
$ENV{'TZ'} = "GMT";
for ($clock = 2147483641; $clock < 2147483651; $clock++)
{
print ctime($clock);
}
Этот perl-скрипт обеспечивает вывод ниже:
Family-iMac:~ dude$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.11.6
BuildVersion: 15G1004
Family-iMac:~ dude$ /Users/dude/Desktop/2038.pl
Tue Jan 19 03:14:01 2038
Tue Jan 19 03:14:02 2038
Tue Jan 19 03:14:03 2038
Tue Jan 19 03:14:04 2038
Tue Jan 19 03:14:05 2038
Tue Jan 19 03:14:06 2038
Tue Jan 19 03:14:07 2038
Tue Jan 19 03:14:08 2038
Tue Jan 19 03:14:09 2038
Tue Jan 19 03:14:10 2038
Информация собрана, а сценарий сжат до минимума с этого очень интересного сайта .
МикроМашина
Громовая Кузня
МикроМашина