Может читать (2) вернуть ноль, когда не в EOF? - PullRequest
8 голосов
/ 19 июня 2010

Согласно справочной странице для read (2), он только возвращает ноль, когда достигается EOF.

Однако, кажется, что это неверно и что иногда он может возвращать ноль, возможно, потому что файл не являетсяготовы читать еще?Должен ли я вызывать select (), чтобы увидеть, готов ли он перед чтением файла с диска?

Обратите внимание, что nBytes: 1,445,888

Пример кода:

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;
  }
}

Выходные данные читаются (когда происходит сбой без чтения данных):

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

Это работает на 32-битном centos4 как виртуальная машина с использованием VMware Server 1.0.10.Читаемая файловая система является локальной для виртуальной машины.Хост-компьютер - 32-разрядный сервер Windows 2008.

Uname -a говорит:

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

Я заметил, что приведенная ниже ссылка http://opengroup.org/onlinepubs/007908775/xsh/read.html указывает:

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. 

Итак, возможно, я получаю сигнал, прерывающий чтение, и, таким образом, возвращаемое значение равно нулю из-за ошибки или из-за того, что считываются нулевые байты?

Ответы [ 3 ]

5 голосов
/ 19 июня 2010

После некоторого исследования, на самом деле есть некоторые обстоятельства, при которых он вернет 0, который вы не могли бы считать «EOF».

Подробную информацию см. В определении POSIX для read ():http://opengroup.org/onlinepubs/007908775/xsh/read.html

Некоторые примечательные из них, если вы попросите его прочитать 0 байтов - дважды проверьте, что вы случайно не передаете ему 0 - и читаете после конца «письменной» частиfile (на самом деле вы можете искать за концом файла, который «расширяет» файл нулями, если вы там пишете, но пока вы не сделаете, «EOF» все еще находится в конце уже написанной части).

Мое лучшее предположение, что у вас где-то возникла проблема с синхронизацией.Некоторые вопросы, которые вам нужно задать: «Как пишутся эти файлы?»и «Я уверен, что они не нулевой длины, когда я пытаюсь их прочитать?».Во втором случае вы можете попробовать запустить stat () для файла, прежде чем читать его, чтобы увидеть его текущий размер.

3 голосов
/ 19 июня 2010

Единственный другой случай, когда я могу думать, что read () возвращает 0, это если вы передаете nbytes как 0; иногда это может произойти, если вы передаете размер чего-то или другого в качестве параметра. Может ли это быть тем, что происходит сейчас?

Если файл не готов к чтению, произойдет чтение, возвращающее -1, и для errno установлено значение EAGAIN.

1 голос
/ 20 июня 2010

Разобрался!У меня было чтение неинициализированной памяти (UMR), и я неправильно искал конец файла.

...