Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

Обычные файлы

Системный вызов был бы запущен повторно В этом случае

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

Поведение BSD несомненно полезно; вы всегда можете сказать, сколько данных было прочитано.

Поведение POSIX сходно, но не идентично первоначальному поведению BSD. POSIX указывает, что

read
[108] завершается с ошибкой
EINTR
лишь в случае появления сигнала до начала перемещения данных. Хотя POSIX ничего не говорит о «медленных устройствах», на практике это условие проявляется именно на них.

108

Хотя мы описываем

read
, эти правила применяются ко всем системным вызовам, которые могут завершиться с ошибкой
EINTR
, как, например, семейство функций
wait
— Примеч. автора.

В противном случае, если сигнал прерывает частично выполненную

read
, возвращенное значение является числом уже прочитанных байтов. По этой причине (а также для возможности обработки коротких файлов) всегда следует проверять возвращаемое
read
значение и никогда не предполагать, что прочитано все запрошенное количество байтов. (Функция POSIX API
sigaction
, описанная позже, позволяет при желании получить поведение повторно вызываемых системных вызовов BSD.)

10.4.4.1. Пример: GNU Coreutils

safe_read
и
safe_write

Для обработки случая EINTR в традиционных системах GNU Coreutils использует две функции,

safe_read
и
safe_write
. Код несколько запутан из-за того, что один и тот же файл за счет включения #include и макросов реализует обе функции. Из файла
lib/safe-read.c
в дистрибутиве Coreutils:

1 /* Интерфейс read и write для .повторных запусков после прерываний.

2 Copyright (С) 1993, 1994, 1998, 2002 Free Software Foundation, Inc.

/* ... куча шаблонного материала опущена... */

56

57 #ifdef SAFE_WRITE

58 # include "safe-write.h"

59 # define safe_rw safe_write /* Создание safe_write */

60 # define rw write /* Использование системного вызова write */

61 #else

62 # include "safe-read.h"

63 # define safe_rw safe_read /* Создание safe_read */

64 # define rw read /* Использование системного вызова read */

65 # undef const

66 # define const /* пусто */

67 #endif

68

69 /* Прочесть (записать) вплоть до COUNT байтов в BUF из(в) дескриптора FD, повторно запуская вызов при

70 прерывании. Вернуть число действительно прочитанных (записанных) байтов, 0 для EOF

71 или в случае ошибки SAFE_READ_ERROR(SAFE_WRITE_ERROR). */

72 size_t

73 safe_rw(int fd, void const *buf, size_t count)

74 {

75 ssize_t result;

76

77 /* POSIX ограничивает COUNT значением SSIZE_MAX, но мы еще больше ограничиваем его, требуя,

78 чтобы COUNT <= INT_MAX, для избежания ошибки в Tru64 5.1.

79 При уменьшении COUNT сохраняйте указатель файла выровненным по размеру блока.

80 Обратите внимание, что read (write) может быть успешным в любом случае, даже если прочитано (записано)

81 менее COUNT байтов, поэтому вызывающий должен быть готов обработать

82 частичные результаты. */

83 if (count > INT_MAX)

84 count = INT_MAX & -8191;

85

86 do

87 {

88 result = rw(fd, buf, count);

89 }

90 while (result < 0 && IS_EINTR(errno));

91

92 return (size_t) result;

93 }

Строки 57–67 обрабатывают определения, создавая соответствующим образом

safe_read
и
safe_write
(см. ниже
safe_write.c
).

Строки 77–84 указывают на разновидность осложнений, возникающих при чтении. Здесь один особый вариант Unix не может обработать значения, превышающие

INT_MAX
, поэтому строки 83–84 выполняют сразу две операции: уменьшают значение числа, чтобы оно не превышало
INT_MAX
, и сохраняют его кратным 8192. Последняя операция служит эффективности дисковых операций: выполнение ввода/вывода с кратным основному размеру дискового блока объемом данных более эффективно, чем со случайными размерами данных. Как отмечено в комментарии, код сохраняет семантику
read
и
write
, где возвращенное число байтов может быть меньше затребованного.

  • Читать дальше
  • 1
  • ...
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: