Обработка ошибок
В предыдущем разделе мы обсудили разницу между системными вызовами и библиотечными функциями. Они также различаются по способу передачи процессу информации об ошибке, произошедшей во время выполнения системного вызова или функции библиотеки.
Обычно в случае возникновения ошибки системные вызовы возвращают ?1 и устанавливают значение переменной errno, указывающее причину возникновения ошибки. Так, например, существует более десятка причин завершения вызова open(2) с ошибкой, и все они могут быть определены с помощью переменной errno. Файл заголовков <errno.h> содержит коды ошибок, значения которых может принимать переменная errno, с краткими комментариями.
Библиотечные функции, как правило, не устанавливают значение переменной errno, а код возврата различен для разных функций.
Поскольку базовым способом получения услуг ядра являются системные вызовы, рассмотрим более подробно обработку ошибок в этом случае.
Переменная errno определена следующим образом: external int errno;
Следует обратить внимание, что значение errno не обнуляется следующим, нормально завершившимся системным вызовом. Таким образом, значение этой переменной имеет смысл только после системного вызова, который завершился с ошибкой.
Стандарт ANSI С определяет две функции, помогающие сообщить причину
ОШИбоЧНОЙ ситуации: strerror(3C) и реггог(ЗС).
Функция strerror(3C) имеет вид:
#include <string.h>
char *strerror(int errnum);
Функция принимает в качестве аргумента errnum номер ошибки и возвращает указатель на строку, содержащую сообщение о причине ошибочной ситуации.
Функция реггог(зс) объявлена следующим образом:
#include <errno.h>
#include <stdio.h>
void perror(const char *s);
Функция выводит в стандартный поток сообщений об ошибках информацию об ошибочной ситуации, основываясь на значении переменной еrrno. Строка s, передаваемая функции, предваряет это сообщение и может служить дополнительной информацией, добавляя, например, название функции или программы, в которой произошла ошибка.
Использование этих двух функций:
#include <errno.h>
#include <stdio.h>
main(int argc, char *argv[])
{
fprintf(stderr, ?ENOMEM: %s\n", strerror(enomem));
ermo = ENOEXEC;
perror(argv[0]);
}
Результат выполнения:
ENOMEM: Not enough space
./program: exec format error
Таблицу с описанием ошибок системных вызовов можно найти в книге А.Робачевского по Unix.