Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект 58 страниц 2002.doc
Скачиваний:
91
Добавлен:
15.06.2014
Размер:
4.07 Mб
Скачать

Обработка ошибок

Обработке ошибок в ОС UNIX уделяется достаточно серьёзное внимание, т. к. написание надёжных и устойчивых программ, особенно для многопользовательских многозадачных систем, является важной задачей.

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

Есть внешний массив sys_errlist, который представляет собой таблицу сообщений об ошибках и имеется внешняя переменная sys_nerr , которая задаёт текущий размер этого массива.

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

#include <string.h>

char * strerror (int errnum);

#include <errno.h>

#include <stdio.h>

void perror (const char *s);

Функция strerror() в качестве аргумента принимает номер ошибки и возвращает указатель на строку, содержащую сообщение о причине ошибочной ситуации.

Функция perror() выводит в стандартный поток сообщений об ошибках info об ошибочных ситуациях, основываясь на значении переменной errno. Строка, передаваемая функции в качестве аргумента, предваряет это сообщение об ошибке и может использоваться в качестве дополнительной информации.

#include <string.h>

#include <errno.h>

#include <stdio.h>

main (int argc, char *argv [ ] )

{

fprintf (stderr, “enomem: %s \n”, strerror (ENOMEM));

errno = ENOEXEC;

perror (argv [0] );

}

$prog.out

ENOMEM: Not enough space

Prog.out: Exec format error

Ошибки имеют мнемоническое значение, т. Е. За именем каждой ошибки стоит определённый индекс массива sys_errlist.

Наиболее часто встречающиеся ошибки:

  1. E2BIG – слишком длинный список аргументов в системном вызове exec ();

  2. EACCES – нет доступа из–за отсутствия прав доступа;

  3. EAGAIN – ресурс временно недоступен, обычно обозначает переполнение некоторой системной таблицы;

  4. EBADF – недопустимый дескриптор файла (используется неоткрытый дескриптор файла);

  5. EBUSY – занято устройство или ресурс (попытка удалить файл, используемый другим приложением);

  6. ECHILD – нет дочерних процессов для системных вызовов wait() и waitpid();

  7. EEXIST – файл уже существует;

  8. EINVAL – недопустимый аргумент, системному вызову передан неверный параметр или список параметров;

  9. EIO – ошибка ввода/вывода;

  10. EMFILE – слишком много открытых процессом файлов;

  11. ENODEV – устройство не существует;

  12. ENOMEM – нет места в памяти;

  13. EPIPE – разрыв связи в канале.

Ограничения для процессов

Так как ОС UNIX является многозадачной системой, то в ходе работы несколько процессов могут конкурировать между собой за доступ к различным ресурсам. Для упрощения распределения ресурсов памяти или дискового пространства каждому из процессов устанавливается набор ограничений. Эти ограничения не носят общесистемного характера, как, к примеру, максимальное число процессов, а устанавливается для каждого процесса отдельно.

Для получения информации о текущих ограничениях и для их изменения используются системные вызовы:

#include <sys/time.h>

#include <sys/resource.h>

int getrlimit (int resource, struct rlimit *rlp);

int setrlimit (int resource, struct rlimit *rlp);

struct rlimit

{

rlim_t rlim_cur;

rlim_t rlim_max;

}

Параметр resource определяет вид ресурса. Параметр rlim_cur определяет изменяемое ограничение, т.е. текущее ограничение процесса на данный ресурс. Параметр rlim_max определяет жесткое ограничение, т.е. максимально возможный значение для данного ресурса.

Любой процесс может изменить текущее значение ограничения ресурса до максимально возможного предела. Жесткое ограничение может быть изменено в сторону увеличения только процессами с привилегиями супер-пользователя. Обычные процессы могут только уменьшать значение жёсткого ограничения. Ограничения устанавливаются при инициализации системы и затем наследуются аппаратурными процессами. Для жёсткого ограничения может быть установлено значение, определяемое как RLIM_INFINITY. В этом случае физические ограничения системы будут определять реальный предел использования того или иного ресурса (например: размер памяти или дискового пространства).

Имеются следующие мнемонические ограничения:

  • RLIMIT_CORE  это максимальный размер создаваемого файла core. Если предел 0, то файл создаваться не будет.

  • RLIMIT_CPU  максимальное время использования процессора в секунду. При превышении предела процессу посылается сигнал SIGXCPU.

  • RLIMIT_DATA  максимальный размер сегмента данных в байтах. При достижении этого предела последующие вызовы функций распределения памяти возвращаются с ошибкой ENOMEM.

  • RLIMIT_FSIZE  максимальный размер файла, который может создать процесс. При достижении предела процессу отправляется сигнал SIGXFSZ. Если этот сигнал игнорируется, то последующие попытки увеличить размер файла заканчиваются ошибкой E2BIG

  • RLIMIT_NOFILE  максимальное количество назначенных файловых дескрипторов процесса. Когда это значение достигнуто, системные вызовы возвращают ошибку EMFILE.

  • RLIMIT_STACK  максимальный размер стека процесса. При достижении предела процессу отправляется сигнал SIGSEGV.

  • RLIMIT_NPROC  максимальное число процессов с одним реальным пользовательским идентификатором. При достижении этого значения, возвращается ошибка системного вызова fork() EAGAIN.

  • RLIMIT_MEMLOCK  максимальный размер физической памяти, который процесс может заблокировать с помощью системного вызова mlock(). При превышении предела возвращается ошибка EAGAIN.