Appel Non-bloquant pour le descripteur de lecture

j'ai un descripteur fd, que je peux utiliser pour lire en appelant read(fd, buffer,...). Maintenant, je veux vérifier si il n'y a rien à lire avant de faire l'appel, parce que l'appel est bloquant. Comment dois-je faire?

24
demandé sur mu is too short 2011-04-11 05:57:45
la source

7 ответов

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

l'extrait de code ci-dessus va configurer un tel descripteur pour l'accès non-bloquant. Si les données ne sont pas disponibles lorsque vous appelez read, alors l'appel système échouera avec une valeur de retour de -1 et errno est défini à EAGAIN. Voir le fnctl pages de manuel pour plus d'informations.

Alternativement, vous pouvez utiliser sélectionner avec un délai configurable pour vérifier et/ou d'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.

45
répondu Judge Maygarden 2011-04-11 06:28:29
la source

Utiliser select ou poll à la requête si le descripteur de fichier de données sont disponibles pour la lecture:

fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
11
répondu R.. 2011-04-11 06:17:50
la source

Ok,STDIN peut être lu en mode sans blocage que vous le souhaitez. Vous devrez d'abord configurer la socket en 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 de la mémoire 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 tampon de 1024 est arbitraire.

6
répondu Ken Rockot 2011-04-11 06:06:21
la source

je pense que vous devriez utiliser select ou poll fonctions pour vérifier si il y a quelque chose à lire à partir du descripteur.

3
répondu Elalfer 2011-04-11 06:08:29
la source

selon ce que vous faites vous pourriez être en mesure de tourner le problème à l'envers et utiliser select pour vous dire quand votre descripteur de fichier a quelque chose à lire.

1
répondu mu is too short 2011-04-11 06:10:04
la source

Vérifiez L'API ou le système / outil que vous utilisez pour votre programmation spécifique. (descripteurs/descripteurs de fichiers ont de nombreux usages dans la programmation Linux tels que la programmation socket, la manipulation de fichiers, shared_memory,etc.)

par exemple, une fois j'ai utilisé inotify (pour surveiller les événements du système de fichiers). Cette API vous donne la possibilité de créer un fichier non-bloquant à partir du premier point et il n'est pas nécessaire d'utiliser fcntl ou de telles API pour modifier le fichier créé descripteur.

probablement d'autres outils ou API que vous allez utiliser ont une telle fonctionnalité et vous pouvez définir une telle option dans leur initiation ou de telles étapes (cochez cette case en premier).

mais généralement Oui utiliser fcntl est la réponse et il pourrait être intéressant de savoir que l'inotify lui-même utilise fcntl lui-même. (voir les pages de manuel de Linux)

select () peut vous donner la même fonctionnalité qu'il fonctionne sur des descripteurs de fichiers pour surveiller des événements avec un temps limité spécifié mais gardez à l'esprit que l'usage principal de select est pour la surveillance plusieurs descripteurs de fichiers.

1
répondu Novin Shahroudi 2013-09-29 22:45:16
la source
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;

        }
0
répondu Ankur Soni 2017-09-19 13:09:30
la source

Autres questions sur