J'ai un descripteur fd, que je peux utiliser pour lire en appelant read(fd, buffer,...)
. Maintenant, je veux vérifier s'il y a quelque chose à lire avant de faire l'appel, car l'appel est bloquant. Comment puis-je faire cela?
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
L'extrait de code ci-dessus configurera un tel descripteur pour un accès non bloquant. Si les données ne sont pas disponibles lorsque vous appelez read, l'appel système échouera avec une valeur de retour égale à -1 et errno aura la valeur EAGAIN. Voir les pages de manuel fnctl pour plus d’informations.
Vous pouvez également utiliser select avec un délai d’installation configurable pour vérifier et/ou attendre un intervalle de temps spécifié pour plus de données. Cette méthode est probablement ce que vous voulez et peut être beaucoup plus efficace.
Utilisez select
ou poll
pour demander si le descripteur de fichier a des données disponibles en lecture:
fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
Ok, STDIN
peut être lu en mode non bloquant comme vous le souhaitez. Vous devez d’abord régler le socket sur le mode non bloquant, comme dans
int flags = fcntl(fd, F_GETFL, 0);
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK))
;// some kind of fail
Lorsque vous êtes prêt à lire les données du tampon, vous pouvez tenter une lecture comme suit:
int count;
char buffer[1024];
count = read(fd, buffer, 1024);
if(count < 0 && errno == EAGAIN) {
// If this condition passes, there is no data to be read
}
else if(count >= 0) {
// Otherwise, you're good to go and buffer should contain "count" bytes.
}
else {
// Some other error occurred during read.
}
Notez bien sûr que la taille de la mémoire tampon de 1024
est arbitraire.
Je pense que vous devriez utiliser les fonctions select
ou poll
pour vérifier s’il ya quelque chose à lire dans le descripteur.
Selon ce que vous faites, vous pourrez peut-être inverser le problème et utiliser select
pour vous dire quand votre descripteur de fichier a quelque chose à lire.
Consultez l'API ou le système/outil que vous utilisez pour vos besoins spécifiques de programmation. (Les descripteurs/descripteurs de fichiers ont de nombreuses utilisations dans la programmation Linux, telles que la programmation de sockets, la manipulation de fichiers, la mémoire partagée, etc.)
Par exemple, une fois, j'ai utilisé inotify (pour surveiller les événements du système de fichiers). Cette API vous permet de créer un fichier non bloquant à partir du premier point. Il n'est pas nécessaire d'utiliser fcntl ou de telles API pour modifier le descripteur de fichier créé.
Il est probable que d'autres outils ou API que vous allez utiliser possèdent une telle fonctionnalité et vous pouvez définir cette option lors de leur lancement ou de telles étapes (à vérifier en premier lieu).
Mais généralement, oui, utiliser fcntl est la réponse et il peut être intéressant de savoir qu'inotify utilise lui-même fcntl. (reportez-vous aux pages de manuel de Linux)
select () peut vous donner la même fonctionnalité que celle utilisée dans les descripteurs de fichier pour surveiller les événements avec une durée limitée spécifiée, mais gardez à l'esprit que l'utilisation principale de select concerne les descripteurs de surveillance multiples .
use poll for timeout:
struct pollfd p;
int n;
while ((n = poll(&p, 1, iTo)) < 0)
{
if (errno == EAGAIN || errno == EINTR)
continue;
}
if (!n) {
errno = ETIMEDOUT;
}
while ((len = read(Fd, anyBuff, sizeof(anyenter code hereBuff))) < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
}