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

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

Жанры

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

Прежде чем рассмотреть функцию

process
, нам нужно описать, как представлены ошибки системных вызовов и как осуществляется ввод/вывод. Сама функция
process
представлена в разделе 4.4.3 «Чтение и запись».

4.3. Определение ошибок

«Если неприятность может произойти, она случается»

– Закон Мерфи -

«Будь готов»

– Бойскауты -

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

Основные системные вызовы Linux почти всегда возвращают при ошибке -1 и 0 или положительное значение при успехе. Это дает возможность узнать, была операция успешной или нет:

int result;

result = some_system_call(param1, param2);

if (result < 0) {

 /* ошибка, что-нибудь сделать */

} else

 /* все нормально, продолжить */

Знания того, что произошла ошибка, недостаточно. Нужно знать, какая произошла ошибка.

Для этого у каждого процесса есть предопределенная переменная с именем
errno
. Всякий раз, когда системный вызов завершается ошибкой,
errno
устанавливается в один из набора предопределенных значений ошибок
errno
и предопределенные значения ошибок определены в файле заголовка
<errno.h>
.

#include <errno.h> /* ISO С */

extern int errno;

Хотя сама

errno
может быть макросом, который действует подобно переменной
int
 — она не обязательно является действительной целой переменной. В частности, в многопоточном окружении у каждого потока будет своя индивидуальная версия
errno
. Несмотря на это, практически для всех системных вызовов и функций в данной книге вы можете рассматривать
errno
как простую
int
.

4.3.1. Значения

errno

Стандарт POSIX 2001 определяет большое число возможных значений для errno. Многие из них относятся к сетям, IPC или другим специальным задачам. Справочная страница для каждого системного вызова описывает возможные значения

errno
, которые могут иметь место; поэтому вы можете написать код для проверки отдельных ошибок и соответствующим образом обработать их, если это нужно. Возможные значения определены через символические имена. Предусмотренные GLIBC значения перечислены в табл. 4.1.

Таблица 4.1. Значения GLIBC для

errno

Имя Значение
E2BIG
Слишком длинный список аргументов
EACCESS
Доступ запрещен
EADDRINUSE
Адрес используется
EADDRNOTAVAIL
Адрес недоступен
EAFNOSUPPORT
Семейство адресов не поддерживается
EAGAIN
Ресурс недоступен, попытайтесь снова (может быть то же самое значение, что
EWOULDBLOCK
).
EALREADY
Соединение уже устанавливается
EBADF
Ошибочный дескриптор файла.
EBADMSG
Ошибочное сообщение.
EBUSY
Устройство или ресурс заняты
ECANCELED
Отмена операции.
ECHILD
Нет порожденного процесса.
ECONNABORTED
Соединение прервано
ECONNFRFUSED
Соединение отклонено
ECONNRESET
Восстановлено исходное состояние соединения.
EDEADLK
Возможен тупик (deadlock) в запросе ресурса.
EDESTADDRREQ
Требуется адрес назначения
EDOM
Математический аргумент выходит за область определения функции
EDQUOT
Зарезервировано.
EEXIST
Файл существует.
EFAULT
Ошибочный адрес.
EFBIG
Файл слишком большой.
EHOSTUNREACH
Хост недоступен.
EIDRM
Идентификатор удален
EILSEQ
Ошибочная последовательность байтов.
EINPROGRESS
Операция исполняется.
EINTR
Прерванная функция.
EINVAL
Недействительный аргумент.
EIO
Ошибка ввода/вывода.
EISCONN
Сокет (уже) соединен.
EISDIR
Это каталог.
ELOOP
Слишком много уровней символических ссылок.
EMFILE
Слишком много открытых файлов.
EMLINK
Слишком много ссылок.
EMSGSIZE
Сообщение слишком длинное.
EMULTIHOP
Зарезервировано.
ENAMETOOLONG
Имя файла слишком длинное
ENETDOWN
Сеть не работает
ENETRESET
Соединение прервано сетью
ENETUNREACH
Сеть
недоступна.
ENFILE
В системе открыто слишком много файлов.
ENOBUFS
Буферное пространство недоступно.
ENODEV
Устройство отсутствует
ENOENT
Файл или каталог отсутствуют
ENOEXEC
Ошибочный формат исполняемого файла.
ENOLCK
Блокировка недоступна.
ENOLINK
Зарезервировано.
ENOMEM
Недостаточно памяти.
ENOMSG
Сообщение нужного типа отсутствует
ENOPROTOOPT
Протокол недоступен.
ENOSPC
Недостаточно памяти в устройстве.
ENOSYS
Функция не поддерживается.
ENOTCONN
Сокет не соединен.
ENOTDIR
Это не каталог
ENOTEMPTY
Каталог не пустой.
ENOTSOCK
Это не сокет
ENOTSUP
Не поддерживается
ENOTTY
Неподходящая операция управления вводом/выводом
ENXIO
Нет такого устройства или адреса.
EOPNOTSUPP
Операция сокета не поддерживается
EOVERFLOW
Слишком большое значение для типа данных
EPERM
Операция не разрешена
EPIPE
Канал (pipe) разрушен
EPROTO
Ошибка протокола.
EPROTONOSUPPORT
Протокол не поддерживается
EPROTOTYPE
Ошибочный тип протокола для сокета
ERANGE
Результат слишком большой
EROFS
Файловая система только для чтения
ESPIPE
Недействительный поиск
ESRCH
Нет такого процесса
ESTALE
Зарезервировано
ETIMEDOUT
Тайм-аут соединения истек
ETXTBSY
Текстовый файл занят
EWOULDBLOCK
Блокирующая операция (может быть то же значение, что и для
EAGAIN
)
EXDEV
Ссылка через устройство (cross-device link)

Многие системы предоставляют также другие значения ошибок, а в более старых системах может не быть всех перечисленных значений ошибок. Полный список следует проверить с помощью справочных страниц intro(2) и errno(2) для локальной системы.

ЗАМЕЧАНИЕ.

errno
следует проверять лишь после того, как возникла ошибка и до того, как сделаны дальнейшие системные вызовы. Начальное значение той переменной 0. Однако, в промежутках между ошибками ничто не изменяет ее значения, это означает, что успешный системный вызов не восстанавливает значение 0. Конечно, вы можете вручную установить ее в 0 в самом начале или когда захотите, однако это делается редко.

Сначала мы используем

errno
лишь для сообщений об ошибках. Для этого имеются две полезные функции. Первая —
perror
:

#include <stdio.h> /* ISO С */

void perror(const char *s);

Функция

perror
выводит предоставленную программой строку, за которой следует двоеточие, а затем строка, описывающая значение
errno
:

if (some_system_call(param1, param2) < 0) {

 perror("system call failed");

 return 1;

}

Мы предпочитаем функцию

strerror
, которая принимает параметр со значением ошибки и возвращает указатель на строку с описанием ошибки:

#include <string.h> /* ISO С */

char *strerror(int errnum);

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

if (some_system_call(param1, param2) < 0) {

 fprintf(stderr, "%s: %d, %d: some_system_call failed: %s\n",

argv[0], param1, param2, strerror(errno));

 return 1;

}

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

4.3.2. Стиль сообщения об ошибках

Для использования в сообщениях об ошибках С предоставляет несколько специальных макросов. Наиболее широкоупотребительными являются

__FILE__
и
__LINE__
, которые разворачиваются в имя исходного файла и номер текущей строки в этом файле. В С они были доступны с самого начала. C99 определяет дополнительный предопределенный идентификатор,
__func__
, который представляет имя текущей функции в виде символьной строки. Макросы используются следующим образом:

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

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Уязвимость

Рам Янка
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Уязвимость

Войны Наследников

Тарс Элиан
9. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Войны Наследников

Законы рода

Flow Ascold
1. Граф Берестьев
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Законы рода

«Три звезды» миллиардера. Отель для новобрачных

Тоцка Тала
2. Три звезды
Любовные романы:
современные любовные романы
7.50
рейтинг книги
«Три звезды» миллиардера. Отель для новобрачных

Мимик нового Мира 13

Северный Лис
12. Мимик!
Фантастика:
боевая фантастика
юмористическая фантастика
рпг
5.00
рейтинг книги
Мимик нового Мира 13

Месть за измену

Кофф Натализа
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть за измену

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Не грози Дубровскому! Том 11

Панарин Антон
11. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том 11

Наваждение генерала драконов

Лунёва Мария
3. Генералы драконов
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Наваждение генерала драконов

Огненный князь 4

Машуков Тимур
4. Багряный восход
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Огненный князь 4

Мужчина не моей мечты

Ардова Алиса
1. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.30
рейтинг книги
Мужчина не моей мечты

Золушка по имени Грейс

Ром Полина
Фантастика:
фэнтези
8.63
рейтинг книги
Золушка по имени Грейс