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

на главную

Жанры

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

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

Шрифт:

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

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

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

argv[0], __func__, __FILE__, __LINE__,

param1, param2, strerror(errno));

 return 1;

}

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

Таблица 4.2. Диагностические идентификаторы C99

Идентификатор Версия С Значение
__DATE__
C89 Дата компиляции в виде «
Mmm nn yyyy
»
__FILE_
Оригинальная Имя исходного файла в виде «
program.c
»
__LINE__
Оригинальная Номер строки исходного файла в виде 42
__TIME__
C89 Время компиляции в виде «
hh:mm:ss
»
__func__
C99 Имя текущей функции, как если бы было объявлено
const char __func__[] = "name"

Использование

__FILE__
и
__LINE__
было вполне обычно для ранних дней Unix, когда у большинства людей были исходные коды и они могли находить ошибки и устранять их. По мере того, как системы Unix становились все более коммерческими, использование этих идентификаторов постепенно уменьшалось, поскольку знание положения в исходном коде дает немного пользы, когда имеется лишь двоичный исполняемый файл.

Сегодня, хотя системы GNU/Linux поставляются с исходными кодами, указанный исходный код часто не устанавливается по умолчанию. Поэтому использование этих идентификаторов для сообщений об ошибках не представляет дополнительной ценности. GNU Coding Standards даже не упоминает их.

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

Искушение генерала драконов

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

Идеальный мир для Лекаря

Сапфир Олег
1. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря

Третье правило дворянина

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

Третий. Том 2

INDIGO
2. Отпуск
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 2

Лорд Системы 11

Токсик Саша
11. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 11

Обыкновенные ведьмы средней полосы

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Обыкновенные ведьмы средней полосы

Купеческая дочь замуж не желает

Шах Ольга
Фантастика:
фэнтези
6.89
рейтинг книги
Купеческая дочь замуж не желает

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Неверный

Тоцка Тала
Любовные романы:
современные любовные романы
5.50
рейтинг книги
Неверный

Неудержимый. Книга VI

Боярский Андрей
6. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга VI

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

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

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

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

Без шансов

Семенов Павел
2. Пробуждение Системы
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Без шансов

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия