ERRNO(3) Руководство программиста Linux ERRNO(3)

ИМЯ

errno - код последней ошибки

ОБЗОР

#include <errno.h>

ОПИСАНИЕ

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

Значение errno имеет смысл только тогда, когда вызов возвратил ошибку (а именно: -1 — для большинства системных вызовов; NULL — для большинства библиотечных функций); при успешном выполнении функции также могут менять значение errno. Системные вызовы и библиотечные функции никогда не присваивают errno значение нуля.

Некоторые системные вызовы или библиотечные функции (например, getpriority(2)), при успешном выполнении возвращают -1. В этих случаях успешность выполнения можно отличить от ошибки присвоив errno значение нуля перед вызовом, и затем, если вызов вернул состояние, которое может указывать на ошибку, проверить, равно ли errno ненулевому значению.

Переменная errno определена в стандарте ISO C как изменяемое lvalue int и не объявляемая явно; errno может быть и макросом. Переменная errno является локальным значением нити; её изменение в одной нити не влияет на её значение в другой нити.

Номера и имена ошибок

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

Всем названиям ошибок, определённым в POSIX.1, должны соответствовать разные значения, за исключением EAGAIN и EWOULDBLOCK, которые могут быть одинаковыми.

В разных системах UNIX символическим именам ошибок назначены разные номера, и это верно даже в Linux для разных архитектур. Поэтому числовые значение не указаны в представленном далее списке имён ошибок. Для преобразования этих имён в текстовые сообщения об ошибках можно использовать функции perror(3) и strerror(3).

В любой системе Linux можно получить список всех символических имён ошибок и соответствующие им номера с помощью команды errno(1)) (является частью пакета moreutils):

$ errno -l
EPERM 1 Операция не позволена
ENOENT 2 Нет такого файла или каталога
ESRCH 3 Нет такого процесса
EINTR 4 Прерван системный вызов
EIO 5 Ошибка ввода/вывода
...

Команду errno(1) также можно использовать для поиска ошибок по имени или номеру, а также по строке, входящей в описание ошибки:

$ errno 2
ENOENT 2 Нет такого файла или каталога
$ errno ESRCH
ESRCH 3 Нет такого процесса
$ errno -s permission
EACCES 13 Отказано в доступе

Список имён ошибок

В представленном далее списки символических имён ошибок у некоторых есть некоторые примечания:

  • POSIX.1-2001: Имя определено в POSIX.1-2001, а также, если не указано обратного, в новых версиях POSIX.1.
  • POSIX.1-2008: Имя определено в POSIX.1-2008, но отсутствует в более старых версиях POSIX.1.
  • C99: Имя определено в C99. Ниже представлен список символических имён ошибок, определённых в Linux:
Слишком длинный список параметров (POSIX.1-2001).
Доступ запрещён (POSIX.1-2001).
Адрес уже используется (POSIX.1-2001).
Адрес недоступен (POSIX.1-2001).
Семейство адресов не поддерживается (POSIX.1-2001).
Ресурс временно недоступен (значение может быть равным EWOULDBLOCK) (POSIX.1-2001).
Соединение уже выполняется (POSIX.1-2001).
Некорректный обмен.
Неправильный дескриптор файла (POSIX.1-2001).
Некорректное состояние дескриптора файла.
Неправильное сообщение (POSIX.1-2001).
Неверный дескриптор запроса.
Неверный код запроса.
Некорректный слот.
Устройство или ресурс заняты (POSIX.1-2001).
Операция отменена (POSIX.1-2001).
Отсутствуют дочерние процессы (POSIX.1-2001).
Номер канала вне диапазона.
Ошибка связи при отправке.
Соединение было прервано (POSIX.1-2001).
В соединении отказано (POSIX.1-2001).
Соединение сброшено другой стороной (POSIX.1-2001).
Предотвращена тупиковая ситуация при обращении к ресурсу (POSIX.1-2001).
Синоним EDEADLK.
Требуется указать адрес назначения (POSIX.1-2001).
Математический аргумент вне области определения функции (POSIX.1, C99).
Превышена дисковая квота (POSIX.1-2001).
Файл существует (POSIX.1-2001).
Неправильный адрес (POSIX.1-2001).
Файл слишком велик (POSIX.1-2001).
Узел выключен.
Узел недоступен (POSIX.1-2001).
В странице памяти аппаратная ошибка.
Идентификатор удалён (POSIX.1-2001).
Неверный или неполный мультибайтный или широкий символ (POSIX.1, C99).
Этот текст взят из описания ошибки glibc; в POSIX.1 эта ошибка звучит как «Недопустимая последовательность байт».
Операция выполняется (POSIX.1-2001).
Прерванный вызов функции (POSIX.1-2001); смотрите signal(7).
Неверный аргумент (POSIX.1-2001).
Ошибка ввода/вывода (POSIX.1-2001).
Сокет подключён (POSIX.1-2001).
Это каталог (POSIX.1-2001).
Является файлом именованного типа.
Ключ с истёкшим сроком.
Ключ был отвергнут службой.
Ключ был отозван.
Уровень 2 остановлен.
Уровень 2 не синхронизирован.
Уровень 3 остановлен.
Уровень 3 сброшен.
Невозможно получить доступ к нужной общей библиотеке.
Обращение к повреждённой общей библиотеке.
Попытка компоновки с слишком большим количеством общих библиотек.
Секция .lib в a.out повреждена
Невозможно непосредственно выполнить общую библиотеку.
Число ссылок вне допустимого диапазона.
Слишком много уровней символьных ссылок (POSIX.1-2001).
Неправильный тип носителя.
Слишком много открытых файлов (POSIX.1-2001). Обычно, это происходит из-за превышения ограничения ресурса RLIMIT_NOFILE, описанного в getrlimit(2).
Слишком много ссылок (POSIX.1-2001).
Сообщение слишком длинное (POSIX.1-2001).
Попытка Multihop (POSIX.1-2001).
Слишком длинное название файла (POSIX.1-2001).
Сеть не работает (POSIX.1-2001).
Соединение прервано из-за сети (POSIX.1-2001).
Сеть недоступна (POSIX.1-2001).
Слишком много открытых файлов в системе (POSIX.1-2001). В Linux это, вероятно, результат достижения ограничения /proc/sys/fs/file-max (смотрите proc(5)).
Не anode.
Недостаточно буферного пространства (POSIX.1 (часть XSI STREAMS)).
Сообщение в голове очереди чтения STREAM отсутствует (POSIX.1-2001).
Нет такого устройства (POSIX.1-2001).
Нет такого файла или каталога (POSIX.1-2001).
Обычно, эта ошибка является результатом указания несуществующего пути или отсутствия одного из компонентов каталогов пути, или указанный путь является символической ссылкой на несуществующий объект.
Ошибка формата выполняемого файла (POSIX.1-2001).
Требуемый ключ недоступен.
Нет доступных блокировок (POSIX.1-2001).
Соединение было разорвано (POSIX.1-2001).
Носитель не найден.
Недостаточно места/невозможно выделить память (POSIX.1-2001).
Нет сообщения желаемого типа (POSIX.1-2001).
Машина не в сети.
Пакет не установлен.
Протокол недоступен (POSIX.1-2001).
На устройстве не осталось места (POSIX.1-2001).
Отсутствую ресурсы STREAM (POSIX.1 (часть XSI STREAMS)).
Нет STREAM (POSIX.1 (часть XSI STREAMS)).
Функция не реализована (POSIX.1-2001).
Требуется блочное устройство.
Сокет не подключён (POSIX.1-2001).
Не каталог (POSIX.1-2001).
Каталог не пуст (POSIX.1-2001).
Состояние нельзя восстановить (POSIX.1-2008).
Не сокет (POSIX.1-2001).
Операция не поддерживается (POSIX.1-2001).
Неподходящая операция управления вводом/выводом (POSIX.1-2001).
Имя не уникально в сети.
Нет такого устройства или адреса (POSIX.1-2001).
Операция не поддерживается на сокете (POSIX.1-2001).
(ENOTSUP и EOPNOTSUPP в Linux имеют одинаковые значения, но согласно POSIX.1 значения этих ошибок должны различаться.)
Значение слишком велико для хранения в таком типе данных (POSIX.1-2001).
Владелец умер (POSIX.1-2008).
Операция не позволена (POSIX.1-2001).
Семейство протоколов не поддерживается.
Обрыв канала (POSIX.1-2001).
Ошибка протокола (POSIX.1-2001).
Протокол не поддерживается (POSIX.1-2001).
Неверный тип протокола для сокета (POSIX.1-2001).
Результат слишком большой (POSIX.1, C99).
Удалённый адрес был изменён.
Это удалённый объект.
Ошибка удалённого ввода/вывода.
Прерванный системный вызов следует перезапустить.
Операция не позволяется из-за RF-kill.
Файловая система доступна только для чтения (POSIX.1-2001).
Невозможно отправить данные после выключения конечной точки передачи.
Недопустимое перемещение (POSIX.1-2001).
Тип сокета не поддерживается.
Нет такого процесса (POSIX.1-2001).
Неактуальный дескриптор файла (POSIX.1-2001).
Эта ошибка может возникать в NFS и других файловых системах.
Ошибка потоков канала.
Таймер истёк (POSIX.1 (часть XSI STREAMS)).
(в POSIX.1 описывается как «в ioctl(2) истекло время ожидания STREAM»)
Время ожидания соединения истекло (POSIX.1-2001).
Слишком много ссылок: невозможно объединить.
Текстовый файл занят (POSIX.1-2001).
Структуру необходимо очистить.
Драйвер протокола не подсоединён.
Слишком много пользователей.
Операция приведёт к блокировке (значение может быть равно EAGAIN) (POSIX.1-2001).
Некорректная ссылка (POSIX.1-2001).
Обмен полон.

ЗАМЕЧАНИЯ

Распространённая ошибка:

if (somecall() == -1) {

    printf("somecall() failed\n");

    if (errno == ...) { ... }
}

Здесь errno может больше не иметь значение результата последнего вызова somecall() (т.е., значение может измениться из-за printf(3)). Если значение errno важно, то его нужно сохранять между библиотечными вызовами:

if (somecall() == -1) {

    int errsv = errno;

    printf("somecall() failed\n");

    if (errsv == ...) { ... }
}

В некоторых древних системах файл <errno.h> отсутствовал или не объявлял errno, поэтому это нужно было делать вручную (например, extern int errno). Не делайте этого. Это давно уже не нужно, и вызовет проблемы с современными версиями библиотеки C.

СМОТРИТЕ ТАКЖЕ

errno(1), err(3), error(3), perror(3), strerror(3)

2019-03-06