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

на главную

Жанры

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__
, который представляет имя текущей функции в виде символьной строки. Макросы используются следующим образом:

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

Маленькая женщина Большого

Зайцева Мария
5. Наша
Любовные романы:
эро литература
современные любовные романы
5.00
рейтинг книги
Маленькая женщина Большого

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

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

Двойник Короля 4

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

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

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

Вперед в прошлое 5

Ратманов Денис
5. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 5

Уникум

Поселягин Владимир Геннадьевич
1. Уникум
Фантастика:
альтернативная история
4.60
рейтинг книги
Уникум

Принятие

Хайд Адель
3. История Ирэн
Фантастика:
попаданцы
альтернативная история
фэнтези
6.00
рейтинг книги
Принятие

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Агенты ВКС

Вайс Александр
3. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Агенты ВКС

Я не бог. Книга XXXIV

Дрейк Сириус
34. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я не бог. Книга XXXIV

Мы – Гордые часть 8

Машуков Тимур
8. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мы – Гордые часть 8

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый

Адвокат

Константинов Андрей Дмитриевич
1. Бандитский Петербург
Детективы:
боевики
8.00
рейтинг книги
Адвокат

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6