web-dev-qa-db-fra.com

Appel non bloquant pour la lecture du descripteur

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?

30
SmallChess
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.

51
Judge Maygarden

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 */
11
R..

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.

6
Ken Rockot

Je pense que vous devriez utiliser les fonctions select ou poll pour vérifier s’il ya quelque chose à lire dans le descripteur.

3
Elalfer

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.

1
mu is too short

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 .

1
Novin Shahroudi
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
Ankur Soni