Perbedaan antara CLOCK_REALTIME dan CLOCK_MONOTONIC?

206

Bisakah Anda menjelaskan perbedaan antara CLOCK_REALTIMEdan CLOCK_MONOTONICjam dikembalikan oleh clock_gettime()di Linux?

Manakah pilihan yang lebih baik jika saya perlu menghitung waktu yang telah berlalu antara stempel waktu yang dihasilkan oleh sumber eksternal dan waktu saat ini?

Terakhir, jika saya memiliki daemon NTP yang secara berkala menyesuaikan waktu sistem, bagaimana penyesuaian ini berinteraksi dengan masing-masing CLOCK_REALTIMEdan CLOCK_MONOTONIC?

NPE
sumber

Jawaban:

238

CLOCK_REALTIMEmerupakan tebakan terbaik alat berat untuk jam dinding saat ini, waktu hari. Seperti yang dikatakan Ignacio dan MarkR , ini berarti bahwa CLOCK_REALTIMEdapat melompat maju dan mundur ketika sistem time-of-day jam diubah, termasuk oleh NTP.

CLOCK_MONOTONICmewakili waktu jam dinding mutlak berlalu sejak beberapa titik, sewenang-wenang di masa lalu. Itu tidak terpengaruh oleh perubahan pada sistem waktu-hari jam.

Jika Anda ingin menghitung waktu yang telah berlalu antara dua peristiwa yang diamati pada satu mesin tanpa melakukan reboot, CLOCK_MONOTONICadalah pilihan terbaik.

Perhatikan bahwa di Linux, CLOCK_MONOTONICtidak mengukur waktu yang dihabiskan dalam penangguhan, meskipun menurut definisi POSIX seharusnya. Anda dapat menggunakan Linux khusus CLOCK_BOOTTIMEuntuk jam monoton yang terus berjalan selama penundaan.

kaf
sumber
11
Perhatikan bahwa pada kernel yang lebih baru, CLOCK_MONOTONIC_RAW tersedia yang bahkan lebih baik (tidak ada penyesuaian NTP).
Joseph Garvin
14
@JosephGarvin untuk beberapa nilai "lebih baik", mungkin - CLOCK_MONOTONIC_RAW dapat berjalan cepat atau lambat real-time oleh beberapa (atau beberapa ratus) bagian per juta, dan nilainya mungkin bervariasi karena kondisi lingkungan seperti suhu atau tegangan (atau mencuri waktu pada mesin virtual). Pada mesin benar-kerja, NTP melakukan yang terbaik untuk mengurangi semua faktor tersebut dan CLOCK_MONOTONIC lebih dekat mencerminkan kenyataan waktu berlalu.
hobbs
23
Memang, mungkin menarik untuk memiliki CLOCK_MONOTONIC_PARBOILED yang dipengaruhi oleh upaya NTP untuk memperbaiki kesalahan frekuensi, tetapi tidak terpengaruh oleh upayanya untuk memperbaiki kesalahan fase, tapi itu banyak kompleksitas untuk keuntungan yang meragukan :)
hobbs
1
Saya suka poin yang diangkat oleh @hobbs. Bagaimana jika Anda khawatir tentang program yang dapat dipengaruhi oleh penyimpangan jam? Apakah CLOCK_MONOTONICakan menjadi pilihan terbaik dalam skenario itu? mis. Patriot Missile System
sjagr
3
Saya pikir ini juga penting untuk menyebutkan bahwa CLOCK_REALTIME dipengaruhi oleh detik kabisat. Ini berarti akan menghasilkan cap waktu ganda setiap kali lompatan kedua dimasukkan. Terakhir kali ini terjadi pada 30 Juni 2012 dan cukup banyak perangkat lunak mengalami masalah .
user1202136
38

Buku Robert Love, LINUX System Programming 2nd Edition , secara khusus membahas pertanyaan Anda di awal Bab 11, hal 363:

Aspek penting dari sumber waktu monoton TIDAK BUKAN nilai saat ini, tetapi jaminan bahwa sumber waktu meningkat secara linear, dan dengan demikian berguna untuk menghitung perbedaan waktu antara dua sampel

Yang mengatakan, saya percaya dia mengasumsikan proses berjalan pada instance yang sama dari OS, jadi Anda mungkin ingin memiliki kalibrasi berkala berjalan untuk dapat memperkirakan pergeseran.

pengguna2548100
sumber
25

CLOCK_REALTIMEdipengaruhi oleh NTP, dan dapat bergerak maju dan mundur. CLOCK_MONOTONICtidak, dan naik satu tick per tick.

Ignacio Vazquez-Abrams
sumber
15
CLOCK_MONOTONIC dipengaruhi oleh penyesuaian waktu NTP (time slewing). Namun, itu tidak akan melompat.
derobert
3
Tetapi pada kernel yang lebih baru ada CLOCK_MONOTONIC_RAW, yang benar-benar tidak terpengaruh oleh NTP.
Joseph Garvin
1
"centang" - ada ide kasar seberapa besar / panjang / instruksi CPU adalah tanda centang di Linux / amd64? Atau di mana saya bisa mendapatkan dokumen tentang semua ini?
kevinarpe
@ kevinarpe Tidak yakin tapi saya pikir tanda centang didefinisikan sebagai sebagian kecil dari waktu, bukan jumlah siklus CPU, seringkali 1/100 detik.
Stéphane
@ Stéphane: Saya pasti lebih ketat dari 10 ms. Saya pikir Jawa System.nanoTime()menggunakan CLOCK_MONOTONICdan dapat mengukur durasi dari 1000ns atau kurang. Mungkin Anda berpikir tentang waktu sistem, yang terkadang terbatas pada milidetik?
kevinarpe
20

Selain jawaban Ignacio , CLOCK_REALTIMEbisa maju dengan lompatan, dan kadang-kadang mundur. CLOCK_MONOTONICtidak melakukan; hanya terus maju (meskipun mungkin diatur ulang saat reboot).

Aplikasi yang kuat harus mampu mentolerir CLOCK_REALTIMElompatan ke depan sesekali (dan mungkin mundur sangat sedikit sesekali, meskipun itu lebih merupakan kasus tepi).

Bayangkan apa yang terjadi ketika Anda menangguhkan laptop Anda - CLOCK_REALTIMEmelompat maju setelah resume, CLOCK_MONOTONICtidak. Cobalah di VM.

MarkR
sumber
3
CLOCK_MONOTONIC mulai dari 0 saat program dimulai; ini bukan untuk penggunaan antar proses.
Benubird
18
@ Benubird: Itu tidak dimulai pada 0 ketika program dimulai. Itu CLOCK_PROCESS_CPUTIME_ID. Tes cepat: $ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279. Angka itu cocok dengan waktu operasi sistem di Linux, tetapi standar mengatakan itu sewenang-wenang.
derobert
4
Selain itu, saya tidak percaya bahwa perilaku Linux di mana CLOCK_MONOTONICberhenti karena penundaan / melanjutkan adalah POSIX-sesuai. Ini seharusnya menjadi waktu sejak titik tetap di masa lalu, tetapi menghentikan jam dari penundaan / melanjutkan istirahat itu.
kafe
15

POSIX 7 kutipan

POSIX 7 menentukan keduanya di http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html :

CLOCK_REALTIME:

Jam ini mewakili jam yang mengukur waktu nyata untuk sistem. Untuk jam ini, nilai yang dikembalikan oleh clock_gettime () dan ditentukan oleh clock_settime () mewakili jumlah waktu (dalam detik dan nanodetik) sejak Zaman.

CLOCK_MONOTONIC (fitur opsional):

Untuk jam ini, nilai yang dikembalikan oleh clock_gettime () mewakili jumlah waktu (dalam detik dan nanodetik) sejak titik yang tidak ditentukan di masa lalu (misalnya, waktu memulai sistem, atau Epoch). Poin ini tidak berubah setelah waktu start-up sistem. Nilai jam CLOCK_MONOTONIC tidak dapat ditetapkan melalui clock_settime ().

clock_settime()memberikan petunjuk penting: sistem POSIX dapat berubah secara sewenang-wenang CLOCK_REALITMEdengannya, jadi jangan mengandalkan itu mengalir tidak terus-menerus atau maju. NTP dapat diimplementasikan menggunakan clock_settime(), dan hanya dapat mempengaruhi CLOCK_REALITME.

Implementasi kernel Linux tampaknya mengambil waktu boot sebagai zaman untuk CLOCK_MONOTONIC: Titik awal untuk CLOCK_MONOTONIC

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
0

Maaf, tidak ada reputasi untuk menambahkan ini sebagai komentar. Demikian jawabannya sebagai pelengkap.

Tergantung pada seberapa sering Anda akan menelepon clock_gettime(), Anda harus ingat bahwa hanya beberapa "jam" yang disediakan oleh Linux di VDSO (yaitu tidak memerlukan syscall dengan semua overhead satu - yang hanya menjadi lebih buruk ketika Linux menambahkan pertahanan untuk melindungi dari serangan Spectre-like).

Sementara clock_gettime(CLOCK_MONOTONIC,...),, clock_gettime(CLOCK_REALTIME,...)dan gettimeofday()akan selalu sangat cepat (dipercepat oleh VDSO), ini bukan benar untuk, misalnya CLOCK_MONOTONIC_RAW atau salah satu jam POSIX lainnya.

Ini dapat berubah dengan versi kernel, dan arsitektur.

Meskipun sebagian besar program tidak perlu memperhatikan hal ini, mungkin ada lonjakan latensi pada jam yang dipercepat oleh VDSO: jika Anda menekannya tepat ketika kernel memperbarui area memori bersama dengan penghitung jam, ia harus menunggu untuk kernel untuk menyelesaikan.

Inilah "buktinya" (GitHub, untuk menjauhkan bot dari kernel.org): https://github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7

anonim
sumber
0

CLOCK_REALTIME : Waktu absolut (mis. 07/01/2020)

CLOCK_MONOTONIC: Waktu relatif (mis. 5 detik dari sekarang, atau 10 menit yang lalu)

Bitate
sumber