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

133

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

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

Cependant, je peux utiliser la sleep(seconds)fonction, mais cela 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?

ant2009
la source
sleep(/*seconds*/)dans les <unistd.h>œuvres, mais si j'utilise printf("some things")sans \n, cela ne fonctionne pas.
EsmaeelE
Pour une utilisation dans ce cas, nous devons rincer la sortie avec fflush(stdout);après chaqueprintf()
EsmaeelE

Réponses:

179

Oui - les normes POSIX plus anciennes sont définies usleep(), elles sont donc disponibles sous Linux:

   int usleep(useconds_t usec);

LA DESCRIPTION

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

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


usleep()a depuis été obsolète et par la suite supprimé de POSIX; pour le nouveau code, il nanosleep()est préférable:

   #include <time.h>

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

LA DESCRIPTION

nanosleep() suspend l'exécution du thread appelant au moins jusqu'à l'heure spécifiée dans *req soit écoulé, ou 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 msleep()fonction implémentée en utilisant nanosleep(), en continuant le sommeil s'il est interrompu par un signal:

#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;
}
caf
la source
19
Pourquoi continuent-ils à déprécier les fonctions simples pour les fonctions compliquées. Au lieu de vous briser la cervelle en nanoseconde (), autant utiliser usleep pour le moment.
52

Vous pouvez utiliser cette fonction multiplateforme:

#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
la source
3
Lorsque nous n'avons pas _POSIX_C_SOURCE >= 199309L, comme dans le cas de -ansiou -std=c89, je recommanderais d'utiliser à la struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);place de usleep(milliseconds * 1000);. Le crédit va ici .
Josh Sanford le
Très bonne réponse! Remarque, voici la nanosleep()documentation: man7.org/linux/man-pages/man2/nanosleep.2.html . Il serait utile de publier les liens de documentation pour chaque fonction spécifique à la plate-forme utilisée ici.
Gabriel Staples
A noter également que lors de la compilation avec gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testLinux Ubuntu, avec la version gcc 4.8.4, je reçois l'avertissement suivant: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]. La solution consiste à ajouter les 2 définitions suivantes tout en haut de votre code: 1) #define __USE_POSIX199309et 2) #define _POSIX_C_SOURCE 199309L. Les deux sont nécessaires pour obtenir le code à compiler sans aucun avertissement (et pour utiliser également la nanoseconds()fonction, dont il dispose).
Gabriel Staples
Réponse connexe que je viens de faire: stackoverflow.com/a/55860234/4561887
Gabriel Staples
32

Alternativement usleep(), qui n'est pas défini dans POSIX 2008 (bien qu'il ait été défini jusqu'à POSIX 2004, et il est évidemment disponible sur Linux et d'autres plates-formes avec un historique de conformité POSIX), le standard POSIX 2008 définit nanosleep():

nanosleep - sommeil haute résolution

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

La nanosleep()fonction entraînera la suspension du thread actuel de l'exécution jusqu'à ce que l'intervalle de temps spécifié par l' rqtpargument se soit écoulé ou qu'un signal soit délivré au thread appelant, et son action consiste à invoquer une fonction de capture de signal ou à terminer le processus. Le temps de suspension peut être plus long que demandé car la valeur de l'argument est arrondie à un multiple entier de la résolution du sommeil ou en raison de la planification d'une autre activité par le système. Mais, sauf en cas d'interruption par un signal, le temps de suspension ne doit pas être inférieur au temps spécifié par rqtp, tel que mesuré par l'horloge système CLOCK_REALTIME.

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

Jonathan Leffler
la source
24

Au-delà de l' usleep , l'humble select avec des ensembles de descripteurs de fichiers NULL vous permettra de faire une pause avec une précision de l'ordre de la microseconde, et sans risque de SIGALRMcomplications.

sigtimedwait et sigwaitinfo offrent un comportement similaire.

pilcrow
la source
1
«sans risque de sigalarm»: quel risque et quel cas? appeler dormir et s'endormir?
Massimo
2
@Massimo, la spécification liée pour usleep a plusieurs phrases sur le comportement SIGALARM non spécifié. (Fondamentalement, usleep et sleep peuvent être implémentés via l'ancien mécanisme d' alarme , ce qui, vous pouvez imaginer, compliquerait l'utilisation en toute sécurité de usleep et de SIGALARM. Je ne connais aucun système moderne qui le fasse de cette façon, mais il est toujours dans le spec.)
pilcrow
14
#include <unistd.h>

int usleep(useconds_t useconds); //pass in microseconds
Jonathan Leffler
la source
-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
la source
1
Cela ne dort pas pendant des millisecondes et introduit également beaucoup plus de frais généraux, ce qui rend le timing encore plus incertain.
Devolus
1
L'exemple ne dort pas pendant des microsecondes, et ce n'est pas une bonne solution par rapport à l'utilisation de quelque chose comme usleep ().
Victor Ocampo