gcc (GCC) 4.6.3
c89
J'essaie d'utiliser usleep
. Cependant, je reçois toujours l'avertissement suivant:
déclaration implicite de fonction usleep
J'ai inclus le unistd.h
En tête de fichier.
Les pages de manuel mentionnent quelque chose à ce sujet. Mais je ne suis pas sûr de comprendre cela:
usleep():
Since glibc 2.12:
_BSD_SOURCE ||
(_XOPEN_SOURCE >= 500 ||
_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&
!(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
Before glibc 2.12:
_BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
Mais vous ne savez pas ce que je dois faire avec ce qui précède?
Cette liste est les conditions préalables pour avoir usleep
défini. Il s'agit essentiellement d'une expression de type C impliquant #define
variables qui doivent être vraies avant d'inclure le fichier d'en-tête.
Le fichier d'en-tête lui-même ne définira que usleep
à l'intérieur de ce qui est généralement un nid massif de #ifdef
déclarations et les développeurs ont pris le temps de vous dire ce que vous devez faire pour que vous n'ayez pas à passer des heures à essayer de le découvrir vous-même :-)
En supposant que vous utilisez un glibc
2.12 ou mieux, cela signifie que vous devez soit:
La solution la plus simple consiste probablement à compiler simplement avec gcc -D _BSD_SOURCE
ou mettez:
#define _BSD_SOURCE
dans le code avant d'inclure le fichier d'en-tête qui vous donne usleep
.
Vous voudrez probablement les définir avant tout inclut au cas où il y aurait des dépendances entre les différents fichiers d'en-tête.
Cela peut fonctionner: Ajouter -std=gnu99
lors de la compilation avec gcc sous Linux.
Exemple:
arm-linux-gcc -lpthread -std=gnu99 -o test ArmLinuxDataPipe1.2.1.c
Si vous devez obtenir du code hérité qui utilise usleep()
pour compiler, ajoutez ces lignes à un fichier d'en-tête que vous incluez avant toute autre bibliothèque:
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
Ou ajoutez les drapeaux du compilateur -std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L
À votre makefile.
Cela indique à l'environnement que votre programme utilise cette ancienne version de l'API UNIX , dans laquelle usleep()
n'était pas obsolète.
Alternativement - et s'il s'agit d'un nouveau code, certainement - remplacez usleep()
par nanosleep()
, définissez les macros de test de fonctionnalité en fonction de votre version de la bibliothèque, et examinez votre base de code pour d'autres pourritures de bits.
Sous Linux, vous pouvez vérifier quelles valeurs de _XOPEN_SOURCE
Et _POSIX_C_SOURCE
Votre bibliothèque prend en charge dans man feature_test_macros
.
Réponse plus longue: voici ce qui se passe.
Historiquement, il existait plusieurs normes UNIX différentes, et la meilleure pratique éventuelle à laquelle tout le monde a eu recours était de demander au code de spécifier la version de l'API UNIX pour laquelle il a été écrit. Les programmeurs l'ont fait en définissant une macro de test de fonctionnalités.
L'une des premières divisions dans UNIX a été entre le système V d'AT & T et la distribution standard Berkeley (BSD) de l'Université de Californie. Étant donné que System V était la version officielle et que son comportement est devenu celui par défaut, alors que BSD Unix était l'un des premiers logiciels gratuits et utilisé dans de nombreuses universités, il est beaucoup plus courant de voir le code hérité déclarer _BSD_SOURCE
Que _SVID_SOURCE
. La macro _BSD_SOURCE
Essaie notamment d'activer des extensions à partir d'une grande variété de systèmes d'exploitation différents sur une période de plus de quarante ans. Parfois, il est même utilisé comme fourre-tout pour les extensions non standard. Les deux macros sont obsolètes et contrairement à la réponse actuellement acceptée, vous ne devez jamais utiliser l'une ou l'autre dans le nouveau code.
Au cours de ce siècle, il y avait deux normes UNIX, POSIX, qui est devenue une norme IEEE, et la spécification Single Unix (SUS) du groupe Open (X/Open). Le X/Open SUS est un sur-ensemble de POSIX et ce que vous écririez normalement. Il existait auparavant un certain nombre de macros de test de fonctionnalités que vous pouviez déclarer pour activer les versions alors actuelles de ces normes, et celles-ci sont toujours prises en charge pour la compatibilité descendante. Vous pouvez en voir certaines dans le conditionnel que vous avez collé, mais vous n'avez pas à vous en préoccuper lorsque vous écrivez du nouveau code. Une macro qui vérifie le code, _XOPEN_SOURCE_EXTENDED
, est désormais obsolète, mais a historiquement sélectionné une version du SUS de 1995.
En théorie, la macro de test de fonctionnalités correcte à définir sur n'importe quelle version moderne d'UNIX ou Linux est _XOPEN_SOURCE
. Vous devez rechercher le numéro de version le plus récent pris en charge par votre bibliothèque. En pratique, je pense qu'il est prudent de coder défensivement pour définir également _POSIX_C_SOURCE
, Afin de garantir que personne d'autre ne peut le définir de manière incohérente et casser votre code. Votre question est un bon exemple: si vous définissez _XOPEN_SOURCE
Pour la compatibilité descendante, mais que _POSIX_C_SOURCE
Est défini sur une version plus récente ailleurs dans votre chaîne d'outils, la version supérieure de _POSIX_C_SOURCE
aura priorité et usleep()
ne fonctionnera pas.
Donc, ce que ces conditions signifient, c'est que usleep()
n'était pas une fonction POSIX, mais était à un moment présent sur certains systèmes d'exploitation de type BSD, et en a donc fait le SUS en 1995. Il a été déconseillé en 2008, et la sélection de n'importe quelle version de POSIX ou le SUS depuis lors le désactive activement. Par conséquent, il est activé si vous sélectionnez la version 500 ou 600 du SUS (et un autre synonyme obsolète l'allume également), mais déconseillé si vous sélectionnez une version récente de POSIX ou du SUS. Ils sont également activés si vous sélectionnez l'option quoi que ce soit, mais c'est une mauvaise idée.
Ajoutez ce qui suit en haut de votre code:
// For `nanosleep()`:
#include <time.h>
#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L
Et puis utilisez nanosleep()
à la place, pour créer votre propre fonction sleep_us()
pour dormir un nombre défini de microsecondes:
void sleep_us(unsigned long microseconds)
{
struct timespec ts;
ts.tv_sec = microseconds / 1e6; // whole seconds
ts.tv_nsec = (microseconds % 1e6) * 1e3; // remainder, in nanoseconds
nanosleep(&ts, NULL);
}
Pour la compilation et l'exécution sur Linux Ubuntu, j'ai créé un fichier sleep_test.c et utilisé:
gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test
L'utilisation de nanosleep () a plutôt fonctionné pour moi.
Sur une note pertinente: usleep () a été supprimé depuis POSIX-2008 et recommande d'utiliser nanosleep () à la place.