В КУРСЕ?

Разбираемся в теме

Запросили четыре байта, получили три: как правильно читать результат read в Linux

Одна из первых ошибок при системном программировании — считать, что успешное чтение обязательно заполняет весь подготовленный буфер. Вызов read сообщает отдельное число: сколько байтов действительно получено. Именно оно определяет, какую часть данных можно обрабатывать. Запрошенный объём и возвращённый результат связаны, но это не одно и то же.

Сначала разделите три величины

У программы есть файловый дескриптор, буфер и размер запроса. Дескриптор обозначает открытый ресурс; это не строка с именем файла. Буфер предоставляет место для данных. Размер запроса задаёт верхнюю границу чтения, поэтому он должен соответствовать доступной ёмкости буфера. Возвращаемое значение показывает фактический результат операции. Положительный результат означает число прочитанных байтов. Значение меньше запрошенного само по себе не является ошибкой. При чтении обычного файла с положительным размером запроса ноль означает, что достигнут конец файла. При ошибке возвращается минус один, а причина определяется через errno. Эти случаи нужно различать до обработки содержимого.

Проследите один небольшой пример

Представим обычный файл, содержащий семь байтов ABCDEFG, и повторяющееся чтение с запросом по четыре байта. Пусть три последовательных вызова вернули четыре, три и ноль. После первого можно обработать ABCD, после второго — EFG, после третьего новых данных нет. Суммарно получено семь байтов. Если во второй раз программа обработает все четыре позиции буфера, последняя не станет новым байтом файла. Там может остаться прежнее содержимое. В нашем учебном сценарии ошибка особенно заметна: вместо трёх новых байтов программа использует лишнюю позицию. Поэтому размер обработанного блока должен следовать возвращённому значению, а не постоянному числу четыре. Этот принцип сохраняется и для значительно больших буферов.

Не превращайте частный пример в общее обещание

Последовательность четыре, три, ноль иллюстрирует конкретный случай. Чтение из других источников, например канала или терминала, может возвращать меньшие блоки по иным причинам. Для неблокирующего режима отсутствие доступных данных может сообщаться ошибкой EAGAIN, а не концом файла. Обработка такого случая зависит от устройства программы; бесконечный немедленный повтор без ожидания не является универсальным решением. Ещё одна граница: read получает байты и не добавляет завершающий нулевой символ строки. Если дальше нужны строковые операции, формат данных и место для завершения строки необходимо продумать отдельно. Начинающему удобно сначала работать с явной длиной блока. Тогда проверка результата, накопление количества байтов и обнаружение конца файла остаются видимыми, а не прячутся за предположением, что в памяти всегда лежит готовая строка.

Попробуйте на практике

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

  1. Нарисуйте буфер на четыре позиции и исходные данные ABCDEFG. Запишите начальное суммарное число обработанных байтов: ноль.
  2. Для первого результата четыре заполните буфер данными ABCD и увеличьте счётчик на четыре.
  3. Для второго результата три отметьте только EFG как новые данные. Подчеркните, почему четвёртую позицию нельзя включать в обработанный блок.
  4. Для результата ноль завершите учебную последовательность. Отдельно опишите ветвь минус один: она требует анализа ошибки, а не обработки буфера как новых данных.

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

Частые вопросы

Можно ли считать любое короткое чтение концом файла?

Нет. Само положительное число меньше запроса этого не доказывает. Нужно продолжать обработку в соответствии с типом источника и результатами следующих операций.

Почему нельзя сразу пользоваться буфером как строкой?

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

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

Зарегистрируйтесь, чтобы уточнить возможность доступа к этому материалу

Зарегистрироваться
← К списку материалов