Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
70 прерывании. Вернуть число действительно прочитанных (записанных) байтов, 0 для EOF71 или в случае ошибки SAFE_READ_ERROR(SAFE_WRITE_ERROR). */72 size_t73 safe_rw(int fd, void const *buf, size_t count)74 {75 ssize_t result;7677 /* 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;8586 do87 {88 result = rw(fd, buf, count);89 }90 while (result < 0 && IS_EINTR(errno));9192 return (size_t) result;93 }Строки 57–67 обрабатывают определения, создавая соответствующим образом
safe_read()safe_write()safe_write.cСтроки 77–84 указывают на разновидность осложнений, возникающих при чтении. Здесь один особый вариант Unix не может обработать значения, превышающие
INT_MAXINT_MAXread()write()Обратите внимание, что параметр
countINT_MAXsize_tINT_MAXintСтроки 86–90 представляют действительный цикл, повторно осуществляющий операцию, пока она завершается ошибкой
EINTRIS_EINTR()EINTRsafe_write.c1 /* Интерфейс write для повторного запуска после прерываний.2 Copyright (С) 2002 Free Software Foundation, Inc. /* ...куча шаблонного материала опущена... */1718 #define SAFE_WRITE19 #include "safe-read.с"В строке 18
#defineSAFE_WRITEsafe_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;}10.4.5. Состояния гонок и
sig_atomic_tПока обработка одного сигнала за раз выглядит просто: установка обработчика сигнала в
main()SIG_IGNНо что произойдет, если возникнут два идентичных сигнала, один за другим? В частности, что, если ваша система восстановит действие по умолчанию для вашего сигнала, а второй сигнал появится после вызова обработчика, но до того, как он себя восстановит?
Или предположим, что вы используете
bsd_signal()