Apakah ada fungsi tidur alternatif dalam C hingga milidetik?

133

Saya memiliki beberapa kode sumber yang dikompilasi di Windows. Saya mengonversinya untuk dijalankan di Red Hat Linux.

Kode sumber telah menyertakan <windows.h>file header dan pemrogram telah menggunakan Sleep()fungsi untuk menunggu selama milidetik. Ini tidak akan berfungsi di Linux.

Namun, saya bisa menggunakan sleep(seconds)fungsi, tetapi menggunakan integer dalam hitungan detik. Saya tidak ingin mengonversi milidetik ke detik. Apakah ada fungsi tidur alternatif yang dapat saya gunakan dengan kompilasi gcc di Linux?

ant2009
sumber
sleep(/*seconds*/)dalam <unistd.h>karya, tetapi jika saya gunakan dengan printf("some things")tanpa \n, itu tidak berfungsi.
EsmaeelE
Untuk digunakan dalam kasus ini, kita harus menyiram output dengan fflush(stdout);setelah masingprintf()
EsmaeelE

Jawaban:

179

Ya - standar POSIX yang lebih lama ditentukan usleep(), jadi ini tersedia di Linux:

   int usleep(useconds_t usec);

DESKRIPSI

Fungsi usleep () menunda eksekusi utas panggilan untuk (setidaknya) usec microseconds. Tidur dapat diperpanjang sedikit oleh aktivitas sistem apa pun atau oleh waktu yang dihabiskan untuk memproses panggilan atau oleh rincian waktu sistem.

usleep()membutuhkan mikrodetik , jadi Anda harus mengalikan input dengan 1000 agar dapat tidur dalam milidetik.


usleep()sejak itu telah ditinggalkan dan kemudian dihapus dari POSIX; untuk kode baru, nanosleep()lebih disukai:

   #include <time.h>

   int nanosleep(const struct timespec *req, struct timespec *rem);

DESKRIPSI

nanosleep()menunda pelaksanaan utas panggilan sampai setidaknya waktu yang ditentukan *reqtelah berlalu, atau pengiriman sinyal yang memicu permohonan seorang penangan di utas panggilan atau yang menghentikan proses.

Struktur timespec digunakan untuk menentukan interval waktu dengan ketepatan nanosecond. Ini didefinisikan sebagai berikut:

       struct timespec {
           time_t tv_sec;        /* seconds */
           long   tv_nsec;       /* nanoseconds */
       };

Contoh msleep()fungsi yang diterapkan menggunakan nanosleep(), melanjutkan tidur jika terganggu oleh sinyal:

#include <time.h>
#include <errno.h>    

/* msleep(): Sleep for the requested number of milliseconds. */
int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}
kaf
sumber
19
Mengapa mereka terus mencela fungsi sederhana untuk fungsi yang rumit. Alih-alih menghantam otak Anda pada nanosecond () mungkin juga menggunakan tidur untuk saat ini.
52

Anda dapat menggunakan fungsi lintas platform ini:

#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>   // for nanosleep
#else
#include <unistd.h> // for usleep
#endif

void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
    Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
#else
    usleep(milliseconds * 1000);
#endif
}
Bernardo Ramos
sumber
3
Ketika kita tidak memiliki _POSIX_C_SOURCE >= 199309L, seperti dalam kasus -ansiatau -std=c89, saya akan merekomendasikan menggunakan struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);bukan usleep(milliseconds * 1000);. Kredit di sini .
Josh Sanford
Jawaban bagus! Catatan, inilah nanosleep()dokumentasinya: man7.org/linux/man-pages/man2/nanosleep.2.html . Memposting tautan dokumentasi untuk setiap fungsi platform spesifik yang digunakan di sini akan bermanfaat.
Gabriel Staples
Juga mencatat bahwa ketika kompilasi dengan gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testdi Linux Ubuntu, dengan gcc versi 4.8.4, saya mendapatkan peringatan berikut: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. Solusinya adalah dengan menambahkan 2 definisi berikut ke bagian paling atas kode Anda: 1) #define __USE_POSIX199309dan 2) #define _POSIX_C_SOURCE 199309L. Keduanya diharuskan mendapatkan kode untuk dikompilasi tanpa peringatan (dan juga menggunakan nanoseconds()fungsi, yang telah tersedia).
Gabriel Staples
Jawaban terkait yang baru saja saya buat: stackoverflow.com/a/55860234/4561887
Gabriel Staples
32

Sebagai alternatif untuk usleep(), yang tidak didefinisikan dalam POSIX 2008 (meskipun itu didefinisikan hingga POSIX 2004, dan itu jelas tersedia di Linux dan platform lain dengan sejarah kepatuhan POSIX), standar POSIX 2008 mendefinisikan nanosleep():

nanosleep - Tidur resolusi tinggi

#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

The nanosleep()fungsi akan menyebabkan thread saat akan diskors dari eksekusi sampai baik interval waktu yang ditentukan oleh rqtpargumen telah berlalu atau sinyal yang dikirim ke thread memanggil, dan tindakan adalah untuk memanggil fungsi sinyal-catching atau untuk mengakhiri proses. Waktu penskorsan mungkin lebih lama dari yang diminta karena nilai argumen dibulatkan ke kelipatan integer dari resolusi tidur atau karena penjadwalan aktivitas lain oleh sistem. Tetapi, kecuali untuk kasus yang terganggu oleh sinyal, waktu suspensi tidak boleh kurang dari waktu yang ditentukan oleh rqtp, sebagaimana diukur dengan jam sistem CLOCK_REALTIME.

Penggunaan nanosleep()fungsi tidak berpengaruh pada aksi atau penyumbatan sinyal apa pun.

Jonathan Leffler
sumber
24

Di luar usleep , rendah hati pilih dengan file yang NULL deskripsi set akan membiarkan Anda berhenti dengan mikrodetik presisi, dan tanpa resiko SIGALRMkomplikasi.

sigtimedwait dan sigwaitinfo menawarkan perilaku serupa.

pilcrow
sumber
1
'tanpa risiko sigalarm': risiko apa dan kasus apa? menelepon tidur dan tidur?
Massimo
2
@ Massimo, spec tertaut untuk usleep memiliki beberapa kalimat tentang perilaku SIGALARM yang tidak ditentukan. (Pada dasarnya, usleep dan tidur diperbolehkan untuk dilaksanakan melalui tua alarm mekanisme, yang dapat Anda bayangkan akan menyulitkan penggunaan yang aman dari usleep dan SIGALARM. Saya tidak tahu dari setiap sistem modern yang melakukannya dengan cara ini, tapi masih dalam spec.)
pilcrow
14
#include <unistd.h>

int usleep(useconds_t useconds); //pass in microseconds
Jonathan Leffler
sumber
-7
#include <stdio.h>
#include <stdlib.h>
int main () {

puts("Program Will Sleep For 2 Seconds");

system("sleep 2");      // works for linux systems


return 0;
}
Odin
sumber
1
Ini tidak akan tidur selama milidetik dan juga memperkenalkan lebih banyak overhead, yang membuat waktu lebih tidak dapat diandalkan.
Devolus
1
Contoh tidak tidur untuk mikrodetik, ditambah ini bukan solusi yang baik dibandingkan dengan hanya menggunakan sesuatu seperti usleep ().
Victor Ocampo