Esiste una funzione di sonno alternativa in C a millisecondi?


133

Ho del codice sorgente compilato su Windows. Lo sto convertendo per funzionare su Red Hat Linux.

Il codice sorgente ha incluso il <windows.h>file header e il programmatore ha usato la Sleep()funzione per attendere un periodo di millisecondi. Questo non funzionerà su Linux.

Tuttavia, posso usare la sleep(seconds)funzione, ma utilizza numeri interi in pochi secondi. Non voglio convertire millisecondi in secondi. Esiste una funzione sleep alternativa che posso usare con la compilazione gcc su Linux?


sleep(/*seconds*/)in <unistd.h>opere, ma se io uso con printf("some things"), senza \n, la sua non funziona.
EsmaeelE,

Per l'uso in questo caso, è necessario scaricare l'output con fflush(stdout);after eachprintf()
EsmaeelE

Risposte:


179

Sì - definiti standard POSIX precedenti usleep(), quindi disponibile su Linux:

   int usleep(useconds_t usec);

DESCRIZIONE

La funzione usleep () sospende l'esecuzione del thread chiamante per (almeno) microsecondi usec. Il sonno può essere leggermente allungato da qualsiasi attività di sistema o dal tempo impiegato per l'elaborazione della chiamata o dalla granularità dei timer di sistema.

usleep()richiede microsecondi , quindi dovrai moltiplicare l'input per 1000 per dormire in millisecondi.


usleep()da allora è stato deprecato e successivamente rimosso da POSIX; per il nuovo codice, nanosleep()è preferito:

   #include <time.h>

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

DESCRIZIONE

nanosleep()sospende l'esecuzione del thread chiamante fino a quando non *reqè trascorso almeno il tempo specificato in oppure il recapito di un segnale che attiva l'invocazione di un gestore nel thread chiamante o termina il processo.

La struttura timespec viene utilizzata per specificare intervalli di tempo con precisione in nanosecondi. È definito come segue:

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

Una msleep()funzione di esempio implementata usando nanosleep(), continuando il sonno se viene interrotto da un segnale:

#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;
}

19
Perché continuano a deprecare funzioni semplici per funzioni complicate. Invece di rompere il cervello con il nanosecondo () potrebbe anche usarci per il momento.

52

È possibile utilizzare questa funzione multipiattaforma:

#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
}

3
Quando non abbiamo _POSIX_C_SOURCE >= 199309L, come nel caso di -ansio -std=c89, consiglierei di utilizzare struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);invece di usleep(milliseconds * 1000);. Il merito va qui .
Josh Sanford,

Bella risposta! Nota, ecco la nanosleep()documentazione: man7.org/linux/man-pages/man2/nanosleep.2.html . La pubblicazione dei collegamenti alla documentazione per ciascuna funzione specifica della piattaforma utilizzata qui sarebbe utile.
Gabriel Staples,

Si noti inoltre che quando si compila con gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testsu Linux Ubuntu, con gcc version 4.8.4, ottengo il seguente avvertimento: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. La soluzione consiste nell'aggiungere i seguenti 2 definiti all'inizio del codice: 1) #define __USE_POSIX199309e 2) #define _POSIX_C_SOURCE 199309L. Entrambi sono richiesti per ottenere la compilazione del codice senza alcun avviso (e per utilizzare anche la nanoseconds()funzione che ha a disposizione).
Gabriel Staples,

Risposta correlata Ho appena fatto: stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

In alternativa usleep(), che non è definito in POSIX 2008 (sebbene sia stato definito fino a POSIX 2004, ed è evidentemente disponibile su Linux e altre piattaforme con una storia di conformità POSIX), lo standard POSIX 2008 definisce nanosleep():

nanosleep - sonno ad alta risoluzione

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

La nanosleep()funzione deve sospendere l'esecuzione del thread corrente fino a quando non rqtpè trascorso l'intervallo di tempo specificato dall'argomento o viene inviato un segnale al thread chiamante e la sua azione è invocare una funzione di cattura del segnale o terminare il processo. Il tempo di sospensione potrebbe essere più lungo di quanto richiesto perché il valore dell'argomento viene arrotondato per eccesso a un multiplo intero della risoluzione del sonno o a causa della pianificazione di altre attività da parte del sistema. Tuttavia, tranne nel caso di interruzione di un segnale, il tempo di sospensione non deve essere inferiore al tempo specificato da rqtp, misurato dall'orologio di sistema CLOCK_REALTIME.

L'uso della nanosleep()funzione non ha alcun effetto sull'azione o sul blocco di alcun segnale.


24

Oltre a dormire , l'umile selezione con set di descrittori di file NULL ti consentirà di mettere in pausa con precisione al microsecondo e senza il rischio di SIGALRMcomplicazioni.

sigtimedwait e sigwaitinfo offrono comportamenti simili.


1
'senza il rischio di sigalarm': quale rischio e quale caso? chiamare dormire e dormire?
Massimo

2
@Massimo, la specifica collegata per usleep ha diverse frasi sul comportamento SIGALARM non specificato. (Fondamentalmente, usleep e sleep possono essere implementati tramite il vecchio meccanismo di allarme , che puoi immaginare complicherebbe un uso sicuro di sleep e SIGALARM. Non conosco nessun sistema moderno che lo fa in questo modo, ma è ancora nel spec.)
Pilcrow


-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;
}

1
Questo non dormirà per millisecondi e introduce anche molte più spese generali, il che rende i tempi ancora più inaffidabili.
Devolus

1
L'esempio non dorme per microsecondi, inoltre questo non è un granché di soluzione rispetto al semplice utilizzo di qualcosa come usleep ().
Victor Ocampo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.