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

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

Жанры

Linux программирование в примерах

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

Шрифт:

/* Обработка прерываний и отсоединений. Упрощена для представления */

static void sighandler(int sig) {

 signal(sig, SIG_IGN); /* Отныне этот сигнал игнорировать */

 cleanup; /* Очистка после себя */

 signal(sig, SIG_DFL); /* Восстановление действия по умолчанию */

 raise(sig); /* Повторно отправить сигнал */

}

Установка действия

SIG_IGN
гарантирует, что все последующие появляющиеся сигналы
SIGINT
не повлияют на продолжающийся процесс очистки. Когда функция
cleanup
завершит работу, восстановление действия
SIG_DFL
позволяет системе сделать снимок образа процесса, если это нужно возникшему сигналу. Вызов
raise
восстанавливает сигнал. Затем восстановленный сигнал вызывает действие по умолчанию, которое, скорее всего, завершит программу. (Далее в этой главе мы полностью покажем обработчик сигнала
sort.c
.)

10.4.4. Системные вызовы, допускающие повторный запуск

Значение

EINTR
для
errno
(см. раздел 4.3 «Определение ошибок») указывает, что системный вызов был прерван. Хотя с этим значением ошибки может завершаться большое количество системных вызовов, двумя наиболее значительными являются
read
и
write
. Рассмотрите следующий код:

void handler(int signal) { /* обработка сигналов */ }

int main(int argc, char **argv) {

 signal(SIGINT, handler);

 ...

 while ((count = read(fd, buf, sizeof buf)) > 0) {

/* Обработка буфера */

 }

 if (count == 0)

/* конец файла, очистка и т.п. */

 else if (count == -1)

/* ошибка */

 ...

}

Предположим, что система успешно прочла (и заполнила) часть буфера, когда возник

SIGINT
. Системный вызов
read
еще не вернулся из ядра в программу, но ядро решает, что оно может доставить сигнал. Вызывается
handler
, запускается и возвращается в середину
read
. Что возвратит
read
?

В былые времена (V7, более ранние системы System V)

read
возвратила бы -1 и установила бы
errno
равным
EINTR
. Не было способа сообщить, что данные были переданы. В данном случае V7 и System V действуют, как если бы ничего не случилось: не было перемещений данных в и из буфера пользователя, и смещение файла не было изменено. BSD 4.2 изменила это. Были два случая:

Медленные устройства

«Медленное устройство» является в сущности терминалом или почти всяким другим устройством, кроме обычного файла. В этом случае

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

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

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

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 сохраняйте указатель файла выровненным по размеру блока.

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

Ярар. Начало

Грехов Тимофей
1. Ярар
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ярар. Начало

Андер Арес

Грехов Тимофей
1. Андер Арес
Фантастика:
рпг
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Андер Арес

Гримуар темного лорда V

Грехов Тимофей
5. Гримуар темного лорда
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Гримуар темного лорда V

Имперец. Том 4

Романов Михаил Яковлевич
3. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 4

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

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 3

Шайтан Иван

Тен Эдуард
1. Шайтан Иван
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Шайтан Иван

Эпоха Опустошителя. Том VII

Павлов Вел
7. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том VII

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

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

Рассвет русского царства

Грехов Тимофей
1. Новая Русь
Документальная литература:
историческая литература
5.00
рейтинг книги
Рассвет русского царства

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

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

Двойник короля 13

Скабер Артемий
13. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 13

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

Старый, но крепкий

Крынов Макс
1. Культивация без насилия
Фантастика:
рпг
уся
попаданцы
5.00
рейтинг книги
Старый, но крепкий

Государь

Мазин Александр Владимирович
7. Варяг
Фантастика:
альтернативная история
8.93
рейтинг книги
Государь