Что я должен делать, когда запись возвращает меньший размер?

Я пишу обертку вокруг общих файловых операций и не знаю, как справиться со случаем, когда write возвращает меньший размер, чем предоставленный.

Страница man для write гласит:

Количество записанных байтов может быть меньше количества, если, например, на базовом физическом носителе недостаточно места или обнаружено ограничение ресурса RLIMIT_FSIZE (см. Setrlimit(2)), или вызов был прерван обработчиком сигнала после записав меньше, чем считать байтов. (См. Также трубу (7).)

Из моего понимания вышеизложенного, это смесь ошибок (средняя полная) и побуждения вернуться (прерванный вызов). Если все мои файловые дескрипторы неблокируемые, я не должен получать случай прерывания, и тогда единственной причиной будет ошибка. Я прав?

Пример кода:

int size_written = write(fd, str, count);
if (size_written == -1) {
  if (errno == EAGAIN) {
    // poll on fd and come back later
  } else {
    // throw an error
  }
} else if (size_written < count) {
  // ***************
  // what should I do here ?
  // throw an error ?
  // ***************
}

1 ответ

Решение

Вам необходимо использовать необработанные функции ввода / вывода в цикле:

ssize_t todo = count;

for (ssize_t n; todo > 0; )
{
    n = write(fd, str, todo);
    if (n == -1 && errno != EINTR)
    {
        // error
        break;
    }
    str += n;
    todo -= n;
}

if (todo != 0) { /* error */ }

Особое условие, касающееся EINTR позволяет прерывать вызов записи сигналом, не вызывая сбоя всей операции. В противном случае мы ожидаем, что в конечном итоге сможем записать все данные.

Если вы не можете закончить запись всех данных, потому что ваш файловый дескриптор не блокируется и не может принять какие-либо данные в данный момент, вам нужно сохранить оставшиеся данные и повторить попытку позже, когда дескриптор файла сообщит, что он снова готов к записи.

Другие вопросы по тегам