web-dev-qa-db-fra.com

Existe-t-il une fonction de sommeil alternative en C à quelques millisecondes?

J'ai du code source compilé sous Windows. Je le convertis pour qu'il fonctionne sous Red Hat Linux.

Le code source a inclus le fichier d'en-tête <windows.h> et le programmeur a utilisé la fonction Sleep() pour attendre une période de quelques millisecondes. Cela ne fonctionnera pas sous Linux.

Cependant, je peux utiliser la fonction sleep(seconds), mais elle utilise un entier en secondes. Je ne veux pas convertir des millisecondes en secondes. Existe-t-il une fonction de veille alternative que je peux utiliser avec la compilation gcc sous Linux?

114
ant2009

Oui - ancien POSIX normes définies usleep() , donc disponible sous Linux:

   int usleep(useconds_t usec);

LA DESCRIPTION

La fonction usleep () suspend l'exécution du thread appelant pendant (au moins) usec microsecondes. Le sommeil peut être légèrement prolongé par l’activité du système, par le temps passé à traiter l’appel ou par la granularité des temporisateurs système.

usleep() prend microsecondes , vous devrez donc multiplier l'entrée par 1000 pour pouvoir dormir en millisecondes.


usleep() a depuis été déconseillé puis supprimé de POSIX; pour le nouveau code, nanosleep() est préféré:

   #include <time.h>

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

LA DESCRIPTION

nanosleep() suspend l'exécution du thread appelant jusqu'à ce que soit au moins le temps spécifié dans *req, soit la livraison d'un signal qui déclenche l'appel d'un gestionnaire dans le thread appelant ou qui termine le processus.

La structure timespec est utilisée pour spécifier des intervalles de temps avec une précision nanoseconde. Il est défini comme suit:

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

Un exemple de fonction msleep() implémentée à l'aide de nanosleep(), poursuivant le sommeil s'il est interrompu par un signal:

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

Vous pouvez utiliser cette fonction multi-plateforme:

#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
}
41
Bernardo Ramos

À la place de usleep() , qui n'est pas définie dans POSIX 2008 (bien qu'elle ait été définie jusqu'à POSIX 2004, et qu'il est évidemment disponible sur les plates-formes Linux et autres avec un historique de conformité POSIX), la norme POSIX 2008 définit nanosleep() :

nanosleep - sommeil à haute résolution

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

La fonction nanosleep() doit suspendre l'exécution du thread actuel jusqu'à l'expiration de l'intervalle de temps spécifié par l'argument rqtp ou jusqu'à ce qu'un signal soit envoyé au thread appelant et que son action consiste à appeler une fonction de capture de signal. ou pour terminer le processus. La durée de suspension peut être plus longue que celle demandée car la valeur de l'argument est arrondie à un multiple entier de la résolution de veille ou en raison de la planification d'une autre activité par le système. Toutefois, sauf en cas d'interruption d'un signal, le temps de suspension ne doit pas être inférieur au temps spécifié par rqtp, mesuré par l'horloge système CLOCK_REALTIME.

L'utilisation de la fonction nanosleep() n'a aucun effet sur l'action ou le blocage d'un signal.

31
Jonathan Leffler

Au-delà de utilisation , le modeste sélection avec des ensembles de descripteurs de fichier NULL vous permettra pause avec une précision microseconde, et sans risque de complications SIGALRM.

sigtimedwait et sigwaitinfo offrent un comportement similaire.

24
pilcrow
#include <unistd.h>

int usleep(useconds_t useconds); //pass in microseconds
13
Anonymous