Est-ce que read (2) peut renvoyer zéro lorsqu’il n’est pas à EOF?

Selon la page de manuel de read (2), il ne renvoie que zéro lorsque EOF est atteint.

Cependant, il semble que ce soit incorrect et qu’il peut parfois retourner zéro, peut-être parce que le fichier n’est pas encore prêt à être lu? Dois-je appeler select () pour voir si elle est prête avant de lire un fichier sur le disque?

Notez que nBytes est: 1,445,888

Un exemple de code:

fd_set readFdSet; timeval timeOutTv; timeOutTv.tv_sec = 0; timeOutTv.tv_usec = 0; // Let's see if we'll block on the read. FD_ZERO(&readFdSet); FD_SET(fd, &readFdSet); int selectReturn = ::select(fd + 1, &readFdSet, NULL, NULL, &timeOutTv); if (selectReturn == 0) { // There is still more to read. return false; // But return early. } else if (selectReturn < 0) { clog << "Error: select failure: " << strerror(errno) << endl; abort(); } else { assert(FD_ISSET(fd, &readFdSet)); try { const int bufferSizeAvailable = _bufferSize - _availableIn; if (_availableIn) { assert(_availableIn <= _bufferSize); memmove(_buffer, _buffer + bufferSizeAvailable, _availableIn); } ssize_t got = ::read(fd, _buffer + _availableIn, bufferSizeAvailable); clog << " available: " << bufferSizeAvailable << " availableIn: " << _availableIn << " bufferSize: " << _bufferSize << " got " << got << endl; return got == 0; } catch (Err &err) { err.append("During load from file."); throw; } } 

La sortie lit (quand elle échoue sans lecture de données):

 available: 1445888 availableIn: 0 bufferSize: 1445888 got: 0 

Cela fonctionne sur centos4 32 bits en tant que machine virtuelle utilisant VMware Server 1.0.10. Le système de fichiers en cours de lecture est local sur la machine virtuelle. La machine hôte est Windows Server 2008 32 bits.

Le uname -a dit:

 Linux q-centos4x32 2.6.9-89.0.25.ELsmp #1 SMP Thu May 6 12:28:03 EDT 2010 i686 i686 i386 GNU/Linux 

Je remarque que le lien http://opengroup.org/onlinepubs/007908775/xsh/read.html indiqué ci-dessous indique:

 The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal... If a read() is interrupted by a signal before it reads any data, it will return -1 with errno set to [EINTR]. If a read() is interrupted by a signal after it has successfully read some data, it will return the number of bytes read. 

Donc, peut-être que j’obtiens un signal interrompant la lecture et que la valeur renvoyée est donc nulle à cause d’un bogue ou parce qu’elle pense que zéro octet a été lu?

Après quelques recherches, il y a effectivement des circonstances dans lesquelles il y aura 0 que vous ne pensez pas être “EOF”.

Pour plus de détails, consultez la définition de POSIX pour read (): http://opengroup.org/onlinepubs/007908775/xsh/read.html

Certains sont notables si vous lui demandez de lire 0 octet – vérifiez bien que vous ne lui avez pas accidentellement transmis 0 – et lisez après la fin de la partie “écrite” du fichier (vous pouvez réellement chercher après la fin du fichier, qui “étend” le fichier avec des zéros si vous y écrivez, mais jusqu’à ce que vous ayez fait, “EOF” est toujours à la fin de la partie déjà écrite).

Ma meilleure supposition est que vous entrez dans un problème de timing quelque part. Certaines questions que vous devez poser sont “Comment ces fichiers sont-ils écrits?” et “Est-ce que je suis sûr qu’ils ne sont pas nuls quand j’essaie de les lire?”. Pour le second, vous pouvez essayer de lancer un stat () sur le fichier avant de le lire pour voir sa taille actuelle.

Le seul autre cas que je puisse penser à read () renvoyant 0 est si vous passez des nbytes à 0; cela peut parfois arriver si vous passez la taille de quelque chose ou autre en tant que paramètre. Est-ce que ça pourrait être ce qui se passe en ce moment?

Si le fichier n’est pas prêt à être lu, ce qui doit arriver est que read retourne -1 et errno est défini sur EAGAIN.

Deviner! J’ai eu une lecture de mémoire non initialisée (UMR) et cherchait incorrectement à la fin du fichier.