Читаем Программирование для Linux. Профессиональный подход полностью

■ Выполнение системного вызова иногда прерывается внешними событиями, к каковым относится, например, получение сигнала. Это не обязательно означает ошибку, но ответственность за перезапуск системного вызова возлагается на программу.

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

<p>2.2.3. Коды ошибок системных вызовов</p>

Большинство системных вызовов возвращает 0, если операция выполнена успешно, и ненулевое значение — в случае сбоя. (В некоторых случаях используются другие соглашения. Например, функция malloc() при возникновении ошибки возвращает нулевой указатель. Никогда не помешает прочесть man-страницу, посвященную требуемому системному вызову.) Обычно этой информации достаточно для того, чтобы решить, следует ли продолжать привычное выполнение программы. Но для более специализированной обработки ошибок необходимы дополнительные сведения.

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

Коды ошибок являются целыми числами. Возможные значения задаются макроконстантами препроцессора, которые, по существующему соглашению, записываются прописными буквами и начинаются с литеры "E", например EACCESS и EINVAL. При работе со значениями переменной errno следует всегда использовать макроконстанты, а не реальные числовые значения. Все эти константы определены в файле .

В Linux имеется удобная функция strerror(), возвращающая строковый эквивалент кода ошибки. Эти строки можно включать в сообщения об ошибках. Объявление функции находится в файле .

Есть также функция perror() (объявлена в файле ), записывающая сообщение об ошибке непосредственно в поток stderr. Перед собственно сообщением следует размещать строковый префикс, содержащий имя функции или модуля, ставших причиной сбоя.

В следующем фрагменте программы делается попытка открыть файл. Если это не получается, выводится сообщение об ошибке и программа завершает свою работу. Обратите внимание на то, что в случае успеха операции функция open() возвращает дескриптор открытого файла, иначе — -1.

fd = open("inputfile.txt", O_RDONLY);

if (fd == -1) {

 /* Открыть файл не удалось.

    Вывод сообщения об ошибке и выход. */

 fprintf(stderr, "error opening file: %s\n", strerror(errno));

 exit(1);

}

В зависимости от особенностей программы и используемого системного вызова конкретные действия, предпринимаемые в случае ошибки, могут быть разными: вывод сообщения об ошибке, отмена операции, аварийное завершение программы, повторная попытка и даже игнорирование ошибки. Тем не менее важно включить в программу код, обрабатывающий все возможные варианты ошибок.

Одни из кодов, с которым приходится сталкиваться наиболее часто, особенно в функциях ввода-вывода, — это EINTR. Ряд функций, в частности read(), select() и sleep(), требует определенного времени на выполнение. Они называются блокирующими, так как выполнение программы приостанавливается до тех пор, пока функция не завершится. Но если программа, будучи заблокированной, принимает сигнал, функция завершается, не закончив выполнение операции. В данном случае в переменную errno записывается значение EINTR. Обычно в подобной ситуации следует повторно выполнить системный вызов.

Ниже приведен фрагмент программы, в котором функция chown() меняет владельца файла, определяемого переменной path, назначая вместо него пользователя с идентификатором user_id. Если функция завершается неуспешно, дальнейшие действия программы зависят от значения переменной errno. Обратите внимание на интересный момент: при обнаружении возможной ошибки в самой программе ее выполнение завершается с помощью функции abort() или assert(), вследствие чего генерируется файл дампа оперативной памяти. Анализ этого файла может помочь выяснить природу таких ошибок. В случае невосстанавливаемых ошибок, например нехватки памяти, программа завершается с помощью функции exit(), указывая ненулевой код ошибки: в подобных ситуациях файл дампа оказывается бесполезным.

rval = chown(path, user_id, -1);

if (rval != 0) {

 /* Сохраняем переменную errno, поскольку она будет изменена

    при следующем системном вызове. */

 int error_code = errno;

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных