Waktu UNIX diukur pada komputer Anda, menjalankan UNIX.
Jawaban ini akan membuat Anda tahu apa itu Waktu Universal Terkoordinasi (UTC), Waktu Atom Internasional (TAI), dan SI kedua. Menjelaskan mereka jauh di luar lingkup Unix dan Linux Stack Exchange. Ini bukan Pertukaran Tumpukan Fisika atau Astronomi.
Perangkat keras
Komputer Anda berisi berbagai osilator yang mendorong jam dan timer. Persisnya apa yang berbeda dari komputer ke komputer tergantung pada arsitekturnya. Tetapi biasanya, dan secara umum:
- Ada timer interval yang dapat diprogram (PIT) di suatu tempat, yang dapat diprogram untuk menghitung jumlah osilasi yang diberikan dan memicu interupsi ke unit pemrosesan pusat.
- Ada penghitung siklus pada prosesor pusat yang hanya menghitung 1 untuk setiap siklus instruksi yang dieksekusi.
Teori operasi, dalam istilah yang sangat luas
Kernel sistem operasi menggunakan PIT untuk menghasilkan kutu . Ini mengatur PIT untuk menjalankan bebas, menghitung jumlah osilasi yang tepat untuk interval waktu, katakanlah, seperseratus detik, menghasilkan interupsi, dan kemudian secara otomatis mengatur ulang penghitungan untuk pergi lagi. Ada variasi dalam hal ini, tetapi pada dasarnya ini menyebabkan interupsi kutu dinaikkan dengan frekuensi tetap.
Dalam perangkat lunak, kernel menambahkan counter setiap centang. Ia mengetahui frekuensi centang, karena memprogram PIT sejak awal. Jadi ia tahu berapa banyak kutu yang membentuk sedetik. Ini dapat menggunakan ini untuk mengetahui kapan harus menambah penghitung yang menghitung detik. Yang terakhir ini adalah ide kernel dari "Waktu UNIX". Memang, memang, hanya menghitung ke atas pada tingkat satu per SI detik jika dibiarkan ke perangkat sendiri.
Empat hal menyulitkan ini, yang akan saya sampaikan secara umum.
Perangkat kerasnya tidak sempurna. Seorang PIT yang lembar datanya mengatakan bahwa ia memiliki frekuensi osilator N Hertz mungkin malah memiliki frekuensi (katakanlah) N .00002 Hertz, dengan konsekuensi yang jelas.
Skema ini interoperasinya sangat buruk dengan manajemen daya, karena CPU bangun ratusan kali per detik untuk melakukan sedikit lebih banyak daripada peningkatan angka dalam suatu variabel. Jadi beberapa sistem operasi memiliki apa yang dikenal sebagai desain "tickless". Alih-alih membuat PIT mengirim interupsi untuk setiap centang, kernel bekerja (dari penjadwal tingkat rendah) berapa banyak tick yang akan berlalu tanpa ada kuanta thread yang habis, dan memprogram PIT untuk menghitung berapa banyak tick ke dalam tick. masa depan sebelum mengeluarkan interupsi centang. Ia tahu bahwa itu kemudian harus merekam bagian dari kutu N pada interupsi kutu berikutnya, bukannya 1 kutu.
Perangkat lunak aplikasi memiliki kemampuan untuk mengubah waktu kernel saat ini. Itu bisa menginjak nilainya atau bisa membunuh nilainya. Slewing melibatkan menyesuaikan jumlah kutu yang harus naik untuk menambah penghitung detik. Jadi detik counter tidak selalu mengandalkan pada tingkat satu per SI detik pula , bahkan dengan asumsi osilator sempurna. Melangkah melibatkan hanya menulis nomor baru di penghitung detik, yang biasanya tidak akan terjadi sampai 1 SI detik sejak detik terakhir berlalu.
Kernel modern tidak hanya menghitung detik tetapi juga menghitung nanodetik. Tapi itu konyol dan sering tidak mungkin untuk memiliki interupsi centang sekali per nanodetik. Di sinilah hal-hal seperti penghitung siklus ikut berperan. Kernel mengingat nilai counter siklus pada setiap detik (atau pada setiap tick) dan dapat bekerja keluar, dari saat ini nilai counter ketika sesuatu ingin mengetahui waktu dalam nanodetik, berapa banyak nanodetik harus telah berlalu sejak detik terakhir (atau kutu). Namun, sekali lagi, manajemen daya dan termal memainkan malapetaka karena frekuensi siklus instruksi dapat berubah, sehingga kernel melakukan hal-hal seperti mengandalkan perangkat keras tambahan seperti (katakanlah) Pengatur Acara Presisi Tinggi (HPET).
Bahasa C dan POSIX
Standar perpustakaan bahasa C menggambarkan waktu dalam hal jenis buram, time_t
, jenis struktur tm
dengan berbagai bidang tertentu, dan berbagai perpustakaan fungsi seperti time()
, mktime()
, dan localtime()
.
Singkatnya: bahasa C sendiri hanya menjamin bahwa itu time_t
adalah salah satu tipe data numerik yang tersedia dan bahwa satu-satunya cara yang dapat diandalkan untuk menghitung perbedaan waktu adalah difftime()
fungsinya. Ini adalah standar POSIX yang memberikan jaminan lebih ketat yang time_t
notabene adalah salah satu dari tipe integer dan menghitung detik sejak Zaman . Ini juga merupakan standar POSIX yang menentukan timespec
tipe struktur.
The time()
Fungsi kadang-kadang digambarkan sebagai panggilan sistem. Bahkan, ini belum menjadi panggilan sistem yang mendasarinya pada banyak sistem untuk waktu yang cukup lama, saat ini. Pada FreeBSD, misalnya, panggilan sistem yang mendasarinya adalah clock_gettime()
, yang memiliki berbagai "jam" yang tersedia yang mengukur dalam detik atau detik + nanodetik dalam berbagai cara. Ini adalah panggilan sistem dimana perangkat lunak aplikasi membaca Waktu UNIX dari kernel. ( clock_settime()
Panggilan sistem yang cocok memungkinkan mereka untuk melangkah dan adjtime()
panggilan sistem memungkinkan mereka untuk mematikannya.)
Banyak orang melambaikan standar POSIX dengan klaim yang sangat pasti dan tepat tentang apa yang ditentukannya. Orang-orang seperti itu, lebih sering daripada tidak, tidak benar-benar membaca standar POSIX. Seperti dijelaskan alasannya, ide penghitungan "detik sejak Zaman", yang merupakan ungkapan yang digunakan standar, sengaja tidak menentukan bahwa POSIX detik sama panjangnya dengan SI detik, atau bahwa hasil dari gmtime()
"tentu saja" UTC, terlepas dari penampilannya ". Standar POSIX sengajacukup longgar sehingga memungkinkan untuk (katakanlah) sistem UNIX di mana administrator pergi dan secara manual memperbaiki penyesuaian lompatan kedua dengan mengatur ulang jam seminggu setelah itu terjadi. Memang, alasan menunjukkan bahwa itu sengaja cukup longgar untuk mengakomodasi sistem di mana jam telah sengaja ditetapkan salah untuk beberapa waktu selain waktu UTC saat ini.
UTC dan TAI
Interpretasi Waktu UNIX yang diperoleh dari kernel adalah hingga rutinitas perpustakaan yang berjalan dalam aplikasi. POSIX menentukan identitas antara waktu kernel dan "waktu mogok" di a struct tm
. Tetapi, seperti yang ditunjukkan oleh Daniel J. Bernstein, edisi standar tahun 1997 membuat identitas ini sangat salah, mengacaukan aturan tahun kabisat Kalender Gregorian (sesuatu yang dipelajari oleh anak sekolah) sehingga perhitungannya salah sejak tahun 2100 dan seterusnya. "Lebih terhormat dalam pelanggaran daripada ketaatan" adalah ungkapan yang mudah diingat.
Dan memang benar. Beberapa sistem saat ini mendasarkan interpretasi ini pada rutinitas perpustakaan yang ditulis oleh Arthur David Olson, yang merujuk pada "basis data zona waktu Olson" yang terkenal, biasanya dikodekan dalam file basis data di bawah /usr/share/zoneinfo/
. Sistem Olson memiliki dua mode:
- Kernel "detik sejak Zaman" dianggap menghitung detik UTC sejak 1970-01-01 00:00:00 UTC, kecuali untuk detik kabisat. Ini menggunakan
posix/
set file database zona waktu Olson. Semua hari memiliki 86400 detik kernel dan tidak pernah ada 61 detik dalam satu menit, tetapi mereka tidak selalu panjang SI detik dan jam kernel perlu slewing atau melangkah ketika lompatan detik terjadi.
- Kernel "detik sejak Zaman" dianggap menghitung detik TAI sejak 1970-01-01 00:00:10 TAI. Ini menggunakan
right/
set file database zona waktu Olson. Kernel detik memiliki panjang 1 SI detik dan jam kernel tidak perlu slewing atau stepping untuk menyesuaikan detik kabisat, tetapi waktu yang rusak dapat memiliki nilai seperti 23:59:60 dan hari tidak selalu panjang 86400 kernel detik.
M. Bernstein menulis beberapa alat, termasuk daemontools
alatnya, yang diperlukan right/
karena mereka hanya menambahkan 10 time_t
untuk mendapatkan detik TAI sejak 1970-01-01 00:00:00 TAI. Dia mendokumentasikan ini di halaman manual.
Persyaratan ini (mungkin tanpa sadar) diwarisi oleh toolets seperti daemontools-encore
dan runit
dan oleh Felix von Leitner libowfat
. Gunakan Bernsteinmultilog
, Guentermultilog
, atau Papesvlogd
dengan posix/
konfigurasi Olson , misalnya, dan semua cap waktu TAI64N akan (pada saat penulisan ini) 26 detik di belakang hitungan kedua TAI yang sebenarnya sejak 1970-01-01 00:00:10 TAI.
Laurent Bercot dan saya membahas ini dalam s6 dan nosh, meskipun kami mengambil pendekatan yang berbeda. M. Bercot tai_from_sysclock()
bergantung pada bendera waktu kompilasi. alat nosh yang berurusan dengan TAI64N melihat variabel lingkungan TZ
dan TZDIR
untuk mendeteksi otomatis posix/
dan right/
jika mereka bisa.
Menariknya, dokumen time2posix()
dan posix2time()
fungsi FreeBSD yang memungkinkan setara dengan right/
mode Olson dengan time_t
sebagai TAI detik. Namun mereka tidak diaktifkan.
Sekali lagi…
Waktu UNIX diukur pada komputer Anda yang menjalankan UNIX, oleh osilator yang terdapat di perangkat keras komputer Anda. Itu tidak menggunakan SI detik; ini bukan UTC meskipun mungkin sangat mirip; dan itu dengan sengaja membuat jam Anda salah.
Bacaan lebih lanjut