Bugün öğrendim ki: 32 bitlik tüm bilgisayarların 19 Ocak 2038'de Y2K'da olduğu gibi bir sorun yaşayacağı

2038 Yılı Sorunu (Y2038)

2038 yılı sorunu (Y2038, Y2K38, Y2K38 süper hatası veya Epochalypse olarak da bilinir)[1] , bazı bilgisayar sistemlerinin 19 Ocak 2038 tarihinde UTC 03:14:07'den sonraki zamanları temsil edememesine neden olan bir zamanlama sorunudur.

Sorun, Unix zamanını (Unix çağından (1 Ocak 1970 UTC 00:00:00) bu yana geçen saniye sayısı) ölçen ve bunu işaretli 32 bitlik bir tamsayı olarak depolayan sistemlerde mevcuttur. Veri türü yalnızca −(2³¹) ile 2³¹ − 1 arasında tamsayıları temsil edebilir, bu da düzgün kodlanabilen en son zamanın, çağa (19 Ocak 2038 UTC 03:14:07) 2³¹ − 1 saniye sonra olması anlamına gelir. Bir sonraki saniyeye (03:14:08) geçmeye çalışmak, tamsayının taşmasına neden olur ve değerini −(2³¹) olarak ayarlar, ki sistemler bunu çağa 2³¹ saniye önce (13 Aralık 1901 UTC 20:45:52) olarak yorumlar. Problem, 2000 yılı problemiyle benzer doğada olmasına rağmen, 2000 yılı sorununda onluk sayılarla ilgilenirken, 2038 yılı problemi ikili sayılarla ilgilidir.

Unix zamanını işaretsiz (işaretli değil) 32 bitlik bir tamsayı olarak depolayan sistemler, 7 Şubat 2106 tarihinde UTC 06:28:15'te taşma yaşayacaktır.

2038 yılı problemi ele alınmazsa, zamanı kritik hesaplamalar için kullanan bilgisayar sistemleri ölümcül hatalarla karşılaşabilir. Gelecekteki tarihler kullanan bazı uygulamalar, hatayı zaten yaşamıştır.[4][5] En savunmasız sistemler, nadiren veya hiç güncellenmeyen, eski ve gömülü sistemlerdir. Modern sistemler ve eski sistemlerin yazılım güncellemeleri, taşma olmadan önce 292 milyar yıl geçecek olan 64 bitlik işaretli tamsayılar kullanarak bu sorunu ele alır — bu yaklaşık olarak evrenin tahmini yaşının 21 katıdır.

Neden

[düzenle]

Birçok bilgisayar sistemi, dijital zaman tutma için uluslararası bir standart olan Unix zamanını kullanarak zamanı ve tarihi ölçer. Unix zamanı, ilk Unix sisteminin oluşturulmasına dayalı keyfi bir zaman olan, 1 Ocak 1970 UTC 00:00:00'den bu yana geçen saniye sayısı olarak tanımlanır, bu da Unix çağı olarak adlandırılmıştır.[6]

Unix zamanı geleneksel olarak işaretli 32 bitlik bir tamsayı olarak kodlanmıştır; 32 ikili basamaktan (bitten) oluşan bir veri türü olan ve "işaretli" bir sayının hem pozitif hem de negatif sayıları, yanı sıra sıfırı da temsil edebileceği anlamına gelir ve genellikle iki'ler tümleyeni biçiminde depolanır.[a] Bu nedenle, işaretli 32 bitlik bir tamsayı yalnızca −(2³¹) ile 2³¹ − 1 (dahil) arasındaki tamsayı değerlerini temsil edebilir. Sonuç olarak, işaretli 32 bitlik bir tamsayı Unix zamanını depolamak için kullanılırsa, depolanabilecek en son zaman, çağa 2³¹ − 1 (2.147.483.647) saniye sonra, yani Salı, 19 Ocak 2038 tarihinde 03:14:07'dir.[7] Bu değeri bir saniye daha arttırmaya (2³¹ saniye çağa) çalışan sistemler tamsayı taşması yaşar, işaret biti yanlışlıkla negatif bir sayıyı göstermek üzere çevirir. Bu, tamsayı değerini −(2³¹)'e veya çağa göre değil, çağa 2³¹ saniye önce, yani Cuma, 13 Aralık 1901 tarihinde 20:45:52'ye değiştirir. Buradan itibaren sistemler sıfıra doğru ve ardından tekrar pozitif tamsayılara doğru saymaya devam edecektir. Birçok bilgisayar sistemi zaman hesaplamalarını kritik işlevleri çalıştırmak için kullandığı için, hata ciddi sorunlara neden olabilir.

Savunmasız sistemler

[düzenle]

İşaretli 32 bitlik zaman temsilleri içeren veri yapıları kullanan herhangi bir sistemde başarısızlık riski vardır. Bu veri yapıların tam bir listesini elde etmek neredeyse imkansızdır, ancak Unix zamanı problemi olan iyi bilinen veri yapıları vardır:

İndekslerde zamanı 32 bit olarak kullanan dosya sistemleri

32 bitlik zaman alanları olan veritabanları

UNIX_TIMESTAMP() benzeri komutlara sahip veritabanı sorgu dilleri (örneğin, SQL)

Gömülü sistemler

[düzenle]

Hesaplama veya teşhis günlüğünde tarihler kullanan gömülü sistemler, Y2038 sorunundan en çok etkilenenlerdir.[1] Bilgisayar sistemlerindeki modern 18-24 aylık nesil güncellemesine rağmen gömülü sistemler, bileşeni oldukları makinenin ömrü boyunca çalışacak şekilde tasarlanmıştır. Bu sistemlerden bazılarının 2038'de hala kullanılıyor olması düşünülebilir. Bu sistemlerin çalışmasını sağlayan yazılımı güncelleme pratik olmayabilir veya bazı durumlarda imkansız olabilir, nihayetinde 32 bitlik sınırlamalar düzeltilmek zorunda kalınırsa bunların değiştirilmesi gerekebilir.

Uçuştan otomobil sistemlerine kadar birçok ulaşım sistemi gömülü sistemleri kapsamlı bir şekilde kullanır. Otomotiv sistemlerinde bu, ABS (Anti-Locking Braking System), ESC/ESP (Electronic Stability Control), TCS (Traction Control) ve otomatik dört tekerlekten çekiş; uçaklar ise eylemsiz kılavuzlama sistemleri ve GPS alıcıları kullanabilir.[b] Gömülü sistemlerin başka bir önemli kullanım alanı da, doğru zaman ve tarih depolamasına ihtiyaç duyan ve giderek Unix benzeri işletim sistemlerine dayanan cep telefonları ve İnternet özellikli cihazlar (örneğin yönlendiriciler, kablosuz erişim noktaları, IP kameralar) dahil olmak üzere iletişim cihazlarıdır. Örneğin, Y2038 sorunu, zamanın o tarihe değiştirildiği zaman bazı 32 bit Android çalıştıran cihazın çökmesine ve yeniden başlamasına neden oluyor.[8]

Bununla birlikte, tüm gömülü sistemlerin Y2038 sorunundan etkilenmeyeceği anlamına gelmez, çünkü birçok sistemin tarihlere erişmeye ihtiyacı yoktur. Sadece zaman/tarihler arasındaki farkı ve mutlak zaman/tarihleri izleyen sistemler, hesaplamanın doğası gereği önemli bir sorun yaşamaz. Bu, CARB (California Air Resources Board) gibi düzenlenmiş standartlara dayalı otomotiv teşhisleri için geçerlidir.[9]

Erken sorunlar

[düzenle]

Mayıs 2006'da AOLserver yazılımında Y2038 sorununa erken bir örnek görüldü. Yazılım, "asla" zaman aşımı yapmaması gereken bir veritabanı isteğini ele almak için bir geçici çözümle tasarlanmıştı. Bu özel durumu özel olarak ele almak yerine, ilk tasarım, isteklerin en fazla bir milyar saniye sonra zaman aşımı yapmasını belirten keyfi bir gelecek zaman aşımı tarihi belirledi. Ancak, 2038 kesme tarihine göre bir milyar saniye önce, 13 Mayıs 2006 UTC 01:27:28'dir; bu nedenle bu zamandan sonra gönderilen istekler, kesme tarihinin ötesinde bir zaman aşımı tarihine neden olur. Bu, zaman aşımı hesaplamalarının taşmasına ve yazılımın çökmesine neden olan yazılımın aslında geçmişte olan tarihler döndürmesine neden oldu. Sorun keşfedildiğinde AOLServer yöneticileri yapılandırma dosyasını düzenlemek ve zaman aşımını daha düşük bir değere ayarlamak zorunda kaldılar.[4][5]

Çözümler

[düzenle]

2038 yılı problemi için evrensel bir çözüm yoktur. Örneğin, C dilinde, time_t veri türünün tanımında yapılan herhangi bir değişiklik, tarih ve zaman temsillerinin işaretli 32 bitlik time_t tamsayısının doğasına bağlı olduğu herhangi bir uygulamada kod uyumluluk sorunlarına yol açacaktır. time_t'nin işaretsiz 32 bitlik bir tamsayıya değiştirilmesi, aralığı 2106'ya (özellikle Pazar, 7 Şubat 2106 UTC 06:28:15) kadar uzatırken, 1970 öncesi tarihlerin negatif sayılarla temsil edildiği için bu tarihleri depolayan, geri getiren veya değiştiren programları olumsuz etkileyecektir. Mevcut bir sistemde time_t türünün boyutunun 64 bit'e çıkarılması, yapıların düzeninde ve işlevlerin ikili arayüzünde uyumsuzluklara neden olacaktır.

64 bitlik donanım üzerinde çalışmak üzere tasarlanmış çoğu işletim sistemi, zaten 64 bitlik işaretli time_t tamsayıları kullanmaktadır. 64 bitlik bir değerin kullanılması, yaklaşık 292 milyar yıl sonra, evrenin tahmini yaşının 21 katından daha büyük yeni bir sarılma tarihi getirir.[11] Tarihler üzerinde hesaplamalar yapabilme yeteneği, tm_year'ın yıl için 1900'den başlayarak işaretli 32 bitlik bir tamsayı değeri kullanması gerçeğiyle sınırlıdır. Bu, yılın en fazla 2.147.485.547 (2.147.483.647 + 1900) değerine kadar sınırlandırır.[12]

Alternatif öneriler yapılmıştır (bazıları halihazırda kullanılmaktadır), örneğin, bir çağa (genellikle 1 Ocak 1970 veya 1 Ocak 2000) milisaniye veya mikrosaniye depolamak, işaretli 64 bitlik bir tamsayıda, 292.000 yıl boyunca mikrosaniye çözünürlüğünde minimum aralık sağlar.[13][14] Özellikle, Java ve JavaScript'in mutlak zaman damgalarını "1 Ocak 1970'ten bu yana geçen milisaniye" olarak temsil etmek için 64 bitlik işaretli tamsayı kullanımı, bir sonraki için doğru çalışacaktır. Yeni zaman temsilleri için diğer öneriler, farklı hassasiyetler, aralıklar ve boyutlar (neredeyse her zaman 32 bit'ten daha geniş) sağlar, aynı zamanda atlama saniyelerinin ele alınması gibi diğer ilgili sorunları da çözer. Özellikle, TAI64[15] Uluslararası Atomik Zaman (TAI) standardının, saniyenin ve referans çerçevesinin uluslararası gerçek zamanlı standardının bir uygulamasıdır.

Uygulamalı Çözümler

[düzenle]

Ruby sürümü 1.9.2'den (18 Ağustos 2010'da yayınlandı) itibaren, 32 bitlik time_t'li sistemlerde zamanı işaretli 64 bitlik bir tamsayı olarak depolayarak 2038 yılı hatası düzeltildi[16].

NetBSD sürümü 6.0'dan (Ekim 2012'de yayınlandı) itibaren NetBSD işletim sistemi hem 32 bit hem de 64 bit mimarilerde 64 bitlik time_t kullanır. 32 bitlik time_t ile daha eski bir NetBSD sürümü için derlenmiş uygulamalar, ikili uyumluluk katmanı aracılığıyla desteklenir, ancak bu eski uygulamalar yine de Y2038 sorunundan etkilenecektir.[18]

Mayıs 2014'te yayınlanan 5.5 sürümünden itibaren OpenBSD de hem 32 bit hem de 64 bit mimarilerde 64 bitlik time_t kullanır. NetBSD'nin aksine ikili uyumluluk katmanı yoktur. Bu nedenle, 32 bitlik time_t bekleyen uygulamalar ve zaman değerlerini time_t'den farklı bir yerde depolayan uygulamalar bozulabilir.[19]

Linux, başlangıçta yalnızca 64 bitlik mimarilerde 64 bitlik time_t kullandı; geriye dönük uyumluluk nedeniyle saf 32 bit ABI değiştirilmedi.[20] 2020'nin 5.6 sürümünden itibaren 64 bitlik time_t, 32 bitlik mimarilerde de destekleniyor. Bu özellikle gömülü Linux sistemleri için yapıldı.[21]

GNU C Kütüphanesi, 2021 Ağustos'unda yayınlanan 2.34 sürümünden itibaren, uygun Linux sürümleriyle 32 bitlik platformlarda 64 bitlik time_t kullanımını destekledi. Bu destek, kaynak kodunu derlerken _TIME_BITS ön işleyici makrosunu 64 olarak tanımlayarak etkinleştirilebilir.[22]

FreeBSD, 32 bitlik i386 hariç tüm 32 bit ve 64 bit mimarilerde 64 bitlik time_t kullanıyor; 32 bitlik i386, işaretli 32 bitlik time_t kullanıyor.[23]

Linux için x32 ABI (32 bitlik adreslere sahip ancak işlemciyi 64 bit modunda çalıştıran programlar için bir ortam tanımlar) 64 bitlik time_t kullanır. Yeni bir ortam olduğu için özel uyumluluk önlemlerine gerek yoktu.[20]

Network File System sürüm 4, Aralık 2000'den beri zaman alanlarını struct nfstime4 {int64_t seconds; uint32_t nseconds;} olarak tanımlamıştır.[24] Sürüm 3, işaretsiz 32 bit değerleri struct nfstime3 {uint32 seconds; uint32 nseconds;} olarak destekliyor;.[25] İkinci alanın sıfırın üzerindeki değerleri 1 Ocak 1970'ten sonraki tarihleri gösterir. İkinci alanın sıfırın altındaki değerleri 1 Ocak 1970'ten önceki tarihleri gösterir. Her iki durumda da nseconds (nano saniye) alanı, nihai zaman temsili için ikinci alanına eklenmelidir.

ext4 dosya sistemi, inode boyutları 128 bayttan büyük olduğunda, zaman damgası başına ek 32 bitlik bir alan içerir, 30 biti zaman damgasının nano saniye kısmı için kullanılır ve diğer 2 bit zaman damgası aralığını 2446 yılına kadar genişletir.[26]

XFS dosya sistemi, Linux 5.10'dan itibaren, zaman damgası aralığını 2486 yılına kadar genişleten isteğe bağlı bir "büyük zaman damgaları" özelliğine sahiptir.[27]

OpenVMS'nin yerel API'leri 31 Temmuz 31086'ya kadar zaman damgalarını desteklerken[28], C çalışma zamanı kitaplığı (CRTL) time_t için 32 bitlik tamsayılar kullanıyor.[29] 1998'de yapılan Y2K uyumluluk çalışmaları kapsamında CRTL, zaman aralığını 7 Şubat 2106'ya kadar genişletmek için işaretsiz 32 bitlik tamsayılar kullanacak şekilde değiştirildi.[30]

PostgreSQL sürüm 7.2'den (2002-02-04'te yayınlandı) itibaren timestamp WITHOUT TIMEZONE 64 bit olarak depolanmaktadır.[31][doğrulanmadı]. Önceki sürümler zaten timestamp'i 64 bit olarak depolamaktaydı.[kaynak gerekli]

Ocak 2022'de yayınlanan MySQL 8.0.28'den itibaren FROM_UNIXTIME(), UNIX_TIMESTAMP() ve CONVERT_TZ() işlevleri, onları destekleyen platformlarda 64 bit değerleri işler. Bu, 64 bitlik Linux, macOS ve Windows sürümlerini içerir.[32][33] Daha eski sürümlerde, UNIX_TIMESTAMP() gibi yerleşik işlevler 19 Ocak 2038 UTC 03:14:07'den sonra 0 döndürecektir.[34]

Mayıs 2024'te yayınlanan MariaDB 11.5.1'den itibaren TIMESTAMP veri türü ve FROM_UNIXTIME(), UNIX_TIMESTAMP() ve CONVERT_TZ() işlevleri, 64 bitlik Linux, macOS ve Windows sürümlerinde işaretsiz 32 bitlik değerleri işler.[35] Bu, aralığı 2106-02-07 06:28:15'e kadar genişletti ve kullanıcıların bu zaman damgalı değerleri tabloda depolayabilmelerine, depolama düzeni değiştirmelerine ve mevcut kullanıcı verileriyle tam uyumluluklarını korumalarına olanak sağladı.

Visual C++ 2005'ten itibaren CRT, _USE_32BIT_TIME_T ön işlemci makrası tanımlanmadıkça 64 bitlik time_t kullanır.[36] Ancak, Windows API'si 2038 yılı hatasından etkilenmemektedir, çünkü Windows zamanı içeride 1 Ocak 1601'den bu yana 100 nano saniyelik aralıkların sayısı olarak 64 bitlik işaretli bir tamsayı olarak izler ve bu taşma 30.828 yılına kadar olmayacaktır.[37]

Ayrıca bakınız

[düzenle]

Zaman biçimlendirme ve depolama hataları listeleri, genellikle bu 2038 yılı sorununa neden olan taşmaya benzer sorunları listeler.

GPS haftası numarası taşması, bu 2038 yılı sorunundan farklı bir nedenden ötürü 2038'in daha sonraki bir döneminde tesadüfen gerçekleşecektir.

Notlar

[düzenle]

Referanslar

[düzenle]