Mekanisme pengatur waktu memungkinkan Anda menjadwalkan kernel OS untuk memberi tahu aplikasi ketika waktu yang telah ditentukan telah berlalu. Anda biasanya akan menggunakannya dengan memberikan dua informasi. Pertama, Anda harus menentukan berapa lama waktu yang dibutuhkan penghitung waktu sebelum memberi tahu. Kedua, Anda harus menyiapkan fungsi panggilan balik untuk bertindak saat pemberitahuan itu terjadi.
Pendekatan Tradisional untuk Timer
Mekanisme pengatur waktu di sistem berbasis Linux dan Unix telah berevolusi untuk melayani berbagai kebutuhan. Pendekatan yang berbeda dapat membantu Anda memecahkan berbagai jenis masalah. Namun, Anda akan sering melihat versi pertama dari alarm() mekanisme yang masih digunakan.
Fungsi alarm adalah cara paling sederhana untuk menggunakan pengatur waktu; inilah prototipenya:
tidak ditandatanganike dalamalarm(tidak ditandatanganike dalam detik);
Dengan menggunakan metode ini, Anda hanya dapat menentukan waktu dalam hitungan detik. Ketika waktunya habis, sistem operasi mengirimkan
SIGALRM sinyal ke aplikasi Anda. Untuk memproses kedaluwarsa timer di aplikasi Anda, Anda juga harus menentukan fungsi panggilan balik.Berikut adalah contoh fungsi pengendali sinyal:
#termasuk
#termasuk
#termasuk
#termasukruang kosongtimer_callback(ke dalam tanda tangan)
{
waktu_t sekarang = waktu(BATAL);
printf("Sinyal %d tertangkap pada %li", signum, sekarang);
}
ke dalamutama()
{
sinyal (SIGALRM, timer_callback);
alarm(1);
tidur(3);
kembali0;
}
Kode ini menimbulkan SIGALRM sinyal setelah 1 kedua. Jika Anda ingin menambah waktu tunda menjadi lima detik, hubungi saja alarm (5) alih-alih. Untuk menghentikan timer, berikan nilai 0: tanda bahaya (0).
Ketika waktunya habis, timer yang Anda gunakan tidak akan restart secara berkala. Misalnya, jika Anda ingin menunda satu detik lagi, Anda harus memulai kembali mekanisme dengan panggilan lain ke alarm().
Meskipun mudah digunakan, metode ini memiliki beberapa kelemahan:
- Hanya satu pengatur waktu pada satu waktu.
- Tidak ada dukungan pengatur waktu berkala.
- Anda hanya dapat memberikan periode waktu dalam kelipatan seluruh detik.
- Tidak ada cara untuk mengetahui berapa banyak waktu yang tersisa pada timer.
Simpan kode contoh yang diberikan di atas sebagai alarm.c. Kapan Anda mengkompilasi dan menjalankan itu, program akan memanggil timer_callback berfungsi setelah satu detik. Kemudian akan menunggu dua detik tersisa karena tidur (3) baris, lalu akhiri.
$ gcc -o alarm alarm.c
$ waktu ./alarm
Sinyal 14 tertangkap di 1653490465
nyata 0m1.004s
pengguna 0m0.000s
sys 0m0.003s
Alasan menggunakan perintah waktu adalah untuk dapat melihat waktu. Namun jika melihat hasilnya, total waktu berjalan tidak tiga detik. Hal ini disebabkan oleh SIGALRM sinyal dari tanda bahaya (1) ketika detik pertama habis, sedangkan panggilan sistem disebabkan oleh fungsi sleep (3) sedang berjalan. Ketika sinyal ini tiba, itu mengganggu panggilan sys yang dimulai untuk tidur (3).
Menggunakan Pengatur Waktu Interval
Mekanisme pengatur waktu interval pertama kali tersedia di versi 4.2 BSD. Itu nanti distandarisasi oleh POSIX. Keuntungan utamanya dibandingkan tradisional alarm() metode timer berbasis adalah:
- Memberikan resolusi mikrodetik.
- Ini memungkinkan pengontrolan pengukuran waktu secara lebih rinci melalui tiga mode berbeda.
- Dimungkinkan untuk mengaturnya sekali dan membuatnya berfungsi secara berkala.
- Hal ini dimungkinkan untuk mengetahui berapa lama itu hadir pada saat tertentu.
Prototipe fungsi yang digunakan untuk operasi pewaktu interval adalah sebagai berikut:
#termasuk
ke dalampengatur waktu(ke dalam yang, konstan struct itimerval *Nilai baru, struct itimerval *Nilai lama);
ke dalamgettimer(ke dalam yang, struct itimerval *nilai);strukturwaktu
{
strukturwaktuituInterval;// nilai berikutnya
strukturwaktuituNilai;// nilai sekarang
};
strukturwaktu
{
panjang tv_detik;
panjang tv_penggunaan;
};
Jika Anda ingin mengatur penghitung waktu interval, Anda harus menggunakan waktu struktur. Anda harus memberikan nilai menggunakan struct ini sebagai argumen kedua ke pengatur waktu fungsi.
Misalnya, penghitung waktu interval yang akan memberi tahu aplikasi Anda selama 1 detik dan kemudian setiap 300 milidetik dapat diatur sebagai berikut:
strukturwaktupengatur waktu baru;
strukturwaktutimer lama;newTimer.itValue.tv_sec = 1;
newTimer.itValue.tv_usec = 0;newTimer.itInterval.tv_sec = 0;
newTimer.itInterval.tv_usec = 300 * 1000;
setitimer (ITIMER_REAL, &newTimer, &oldTimer);
Jika ada penghitung waktu interval aktif sebelum nilai baru ditetapkan, nilainya ditransfer ke alamat variabel dari waktu jenis yang diberikan ke parameter ketiga dari fungsi.
Anda dapat mengatur tiga jenis pengatur waktu dengan mekanisme pengatur waktu interval. Tentukan jenis timer di parameter pertama pengatur waktu():
Jenis pengatur waktu | Sinyal | Penjelasan |
---|---|---|
ITIMER_REAL | SIGALRM | Tidak tergantung pada waktu yang dihabiskan oleh aplikasi, dihitung dari total waktu yang telah berlalu. |
ITIMER_VIRTUAL | SIGVTALRM | Dihitung dari waktu ke waktu aplikasi berjalan dalam mode pengguna saja. |
ITIMER_PROF | SIGPROF | Dihitung selama jumlah waktu yang dihabiskan oleh aplikasi dalam mode pengguna dan sistem. |
Anda dapat melihat dari tabel ini bahwa ITIMER_REAL jenis mengirim SIGALRM sinyal, seperti alarm() fungsi.
Menggunakan penghitung waktu interval dan alarm() dalam aplikasi yang sama akan membingungkan. Meskipun Anda dapat melakukan pemeriksaan kedua pada waktu yang tersisa dengan gettimer(), tidak masuk akal untuk menggunakannya secara bersamaan.
Berikut adalah contoh pendefinisian fungsi pengendali sinyal dengan: tajuk debug:
#termasuk
#termasuk
#termasuk
#termasuk
#termasuk
#termasuk
#termasuk
#termasuk "./debug.h"ruang kosongtimer_callback(ke dalam tanda tangan)
{
strukturwaktusekarang;
gettimeofday(&sekarang, BATAL);
printf("Sinyal %d tertangkap pada %li.%03lsaya ", tanda tangan, sekarang.tv_sec, sekarang.tv_usec / 1000);
}ke dalamutama()
{
tidak ditandatanganike dalam tersisa = 3;strukturwaktunew_timer;
strukturwaktuold_timer;new_timer.it_value.tv_sec = 1;
new_timer.it_value.tv_usec = 0;
new_timer.it_interval.tv_sec = 0;
new_timer.it_interval.tv_usec = 300 * 1000;setitimer (ITIMER_REAL, &timer_baru, &lama_timer);
sinyal (SIGALRM, timer_callback);ketika (tidur (tersisa) != 0)
{
jika (errno == EINTR)
debugf("tidur terganggu oleh sinyal");
kalau tidak
errorf("kesalahan tidur %s", strerror (errno));
}
kembali0;
}
Kode di atas menggunakan tidur() berfungsi untuk menunggu selama tiga detik. Selama waktu ini, penghitung waktu interval berjalan, pertama selama satu detik, kemudian pada interval 300 milidetik.
Untuk pemahaman yang lebih baik, simpan dan kompilasi kode sampel dengan nama interval.c:
$ gcc -o interval interval.c
$ waktu ./interval
Sinyal 14 tertangkap di 1653493614.325
debug: tidur terganggu oleh sinyal (interval utama.c: 36)
Sinyal 14 tertangkap di 1653493614.625
debug: tidur terganggu oleh sinyal (interval utama.c: 36)
Sinyal 14 tertangkap di 1653493614.925
debug: tidur terganggu oleh sinyal (interval utama.c: 36)
Sinyal 14 tertangkap di 1653493615.225
debug: tidur terganggu oleh sinyal (interval utama.c: 36)
Sinyal 14 tertangkap di 1653493615.525
...
Seperti yang Anda lihat dari output setelah penghitung waktu berjalan, ia memanggil fungsi panggilan balik setiap 300 milidetik.
Namun, setelah menunggu sedikit lebih lama, Anda akan melihat bahwa aplikasi tidak berhenti. Itu terus menjalankan fungsi panggilan balik setiap 300 milidetik. Jika Anda meningkatkan nilai interval dalam milidetik, Anda akan melihat bahwa aplikasi berhenti. Ini karena area penggunaan tidur() fungsi.
Pentingnya Menggunakan Timer di Linux
Khusus untuk aplikasi waktu nyata, mekanisme pengatur waktu sangat penting. Ini juga merupakan solusi yang digunakan untuk optimasi kinerja. Anda bahkan dapat menggunakannya untuk mengukur waktu aktif atau latensi dalam aplikasi Anda. Penting untuk menggunakan mekanisme pengatur waktu untuk melacak waktu yang telah berlalu dan peristiwa transisi waktu.
Cara Mengkompilasi dan Menginstal Perangkat Lunak Dari Sumber di Linux
Baca Selanjutnya
Topik-topik yang berkaitan
- Pemrograman
- Pemrograman
- Kiat Linux
Tentang Penulis
Seorang insinyur dan pengembang perangkat lunak yang merupakan penggemar matematika dan teknologi. Dia selalu menyukai komputer, matematika dan fisika. Dia telah mengembangkan proyek mesin permainan serta pembelajaran mesin, jaringan saraf tiruan dan perpustakaan aljabar linier. Selain itu terus bekerja pada pembelajaran mesin dan matriks linier.
Berlangganan newsletter kami
Bergabunglah dengan buletin kami untuk kiat teknologi, ulasan, ebook gratis, dan penawaran eksklusif!
Klik di sini untuk berlangganan