Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

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
, где возвращенное число байтов может быть меньше затребованного.

Обратите внимание,

что параметр
count
может и в самом деле быть больше
INT_MAX
, поскольку count представляет тип
size_t
, который является беззнаковым (unsigned).
INT_MAX
является чистым
int
, который на всех современных системах является знаковым.

Строки 86–90 представляют действительный цикл, повторно осуществляющий операцию, пока она завершается ошибкой

EINTR
. Макрос
IS_EINTR
не показан, но он обрабатывает случай в системах, на которых
EINTR
не определен. (Должен быть по крайней мере один такой случай, иначе код не будет возиться с установкой макроса; возможно, это было сделано для эмуляции Unix или POSIX в не-Unix системе.) Вот
safe_write.c
:

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

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

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

17

18 #define SAFE_WRITE

19 #include "safe-read.с"

В строке 18

#define
определяет
SAFE_WRITE
; это связано со строками 57–60 в
safe_read.с
.

10.4.4.2. Только GLIBC:

TEMP_FAILURE_RETRY

Файл <unistd.h> GLIBC определяет макрос TEMP_FAILURE_RETRY, который вы можете использовать для инкапсулирования любого системного вызова, который может при неудачном вызове установить errno в EINTR. Его «объявление» следующее:

#include <unistd.h> /* GLIBC */

long int TEMP_FAILURE_RETRY(expression);

Вот определение макроса:

/* Оценить EXPRESSION и повторять, пока оно возвращает -1 с 'errno',

установленным в EINTR. */

# define TEMP_FAILURE_RETRY(expression) \

 (__extension__ \

({ long int __result; \

do __result = (long int)(expression); \

while (__result == -1L && errno == EINTR); \

__result; }))

Макрос использует расширение GCC к языку С (как обозначено ключевым словом

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

Используя этот макрос, мы могли бы переписать

safe_read
следующим образом:

size_t safe_read(int fd, void const *buf, size_t count) {

 ssize_t result;

 /* Ограничить count, как в ранее приведенном комментарии. */

 if (count > INT_MAX)

count = INT_MAX & ~8191;

 result = TEMP_FAILURE_RETRY(read(fd, buf, count));

 return (size_t)result;

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

Хозяин оков III

Матисов Павел
3. Хозяин Оков
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Хозяин оков III

Эволюционер из трущоб. Том 4

Панарин Антон
4. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 4

Медицинский триллер-2. Компиляция. Книги 1-26

Градова Ирина
Медицинский триллер
Детективы:
триллеры
криминальные детективы
медицинский триллер
5.00
рейтинг книги
Медицинский триллер-2. Компиляция. Книги 1-26

Барону наплевать на правила

Ренгач Евгений
7. Закон сильного
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Барону наплевать на правила

Император Пограничья 8

Астахов Евгений Евгеньевич
8. Император Пограничья
Фантастика:
городское фэнтези
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 8

Бастард

Осадчук Алексей Витальевич
1. Последняя жизнь
Фантастика:
фэнтези
героическая фантастика
попаданцы
5.86
рейтинг книги
Бастард

Кодекс Охотника XXXI

Винокуров Юрий
31. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника XXXI

Дважды одаренный

Тарс Элиан
1. Дважды одаренный
Фантастика:
альтернативная история
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Дважды одаренный

Гибель титанов. Часть 2

Чайка Дмитрий
14. Третий Рим
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Гибель титанов. Часть 2

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Плач феникса

Шебалин Дмитрий Васильевич
8. Чужие интересы
Фантастика:
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Плач феникса

Кодекс Охотника. Книга XXIX

Винокуров Юрий
29. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXIX

Барон ненавидит правила

Ренгач Евгений
8. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Барон ненавидит правила

Бастард Бога (Дилогия)

Матвеев Владимир
Фантастика:
альтернативная история
5.11
рейтинг книги
Бастард Бога (Дилогия)