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

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

9.1.5. Завершение процесса

Завершение процесса включает два шага: окончание процесса с передачей системе статуса завершения и восстановление информации родительским процессом.

9.1.5.1. Определение статуса завершения процесса

Статус завершения (exit status) (известный также под другими именами значения завершения (exit value), кода возврата (return code) и возвращаемого значения (return value)) представляет собой 8-битовое значение, которое родитель может использовать при завершении порожденного процесса (на языке Unix, «когда порожденный кончается (dies)»). По соглашению статус завершения 0 означает, что программа отработала без проблем. Любое ненулевое значение указывает на какую-нибудь разновидность ошибки; программа определяет используемые числа и их значения, если они есть. (Например,

grep
использует 0 для указания, что образец был встречен по крайней мере один раз, 1 означает, что образец вообще не встретился, а 2 означает, что возникла ошибка.) Этот статус завершения доступен на уровне оболочки (для оболочек в стиле оболочки Борна) через специальную переменную
$?
.

Стандарт С определяет две константы, которые следует использовать для полной переносимости на не-POSIX системы:

EXIT_SUCCESS

Программа завершилась без проблем. Для обозначения успеха может также использоваться ноль.

EXIT
_FAILURE

В программе была какая-нибудь проблема.

На практике использование лишь этих значений довольно ограничивает. Вместо этого следует выбрать небольшой набор кодов возврата, документировать их значения и использовать. (Например, 1 для ошибок опций командной строки и аргументов, 2 для ошибок ввода/вывода, 3 для ошибок данных и т.д.) Для удобочитаемости стоит использовать константы

#define
или значения
enum
. Слишком большой список ошибок делает их использование обременительным; в большинстве случаев вызывающая программа (или пользователь) интересуется лишь нулевым или ненулевым значением.

Когда достаточно двоичного разделения успех/неудача, педантичный программист использует

EXIT_SUCCESS
и
EXIT_FAILURE
. Наш собственный стиль более естественный, используя с
return
и
exit
явные константы 0 или 1. Это настолько обычно, что рано заучивается и быстро становится второй натурой. Однако для своих проектов вы сами должны принять решение.

ЗАМЕЧАНИЕ. Для родительского процесса доступны лишь восемь наименее значимых битов значения. Поэтому следует использовать значения в диапазоне 0–255. Как мы вскоре увидим, у чисел 126 и 127 есть традиционные значения (помимо простого «неуспешно»), которых ваши программы должны придерживаться.

Поскольку имеют значение лишь восемь наименее значимых битов, вы никогда не должны использовать отрицательные статусы завершения. Когда из небольших отрицательных чисел выделяются восемь последних битов, они превращаются в большие положительные значения! (Например.
– 1 становится 255, а -5 становится 251.) Мы видели книги по программированию на С, в которых это понималось неправильно — не дайте сбить себя с толку

9.1.5.2. Возвращение из

main

Программа может естественно завершиться одним из двух способов: посредством использования одной из описанных далее функций или возвратившись из

main
. (Третий, более радикальный способ описан далее в разделе 12.4 «Совершение самоубийства:
abort
».) В последнем случае следует использовать явное возвращаемое значение вместо выпадения в конце функции:

/* Правильно */ /* Неправильно */

int main(int argc, char **argv) int main(int argc, char **argv)

{ {

 /* здесь код */ /* здесь код */

 return 0; /* ?? Что возвращает main? */

} }

Стандарт С 1999 г. указывает, что при выпадении в конце, поведение функции

main
должно быть таким, как если бы она возвращала 0. (Это верно также для С++; однако, стандарт С 1989 г. намеренно оставляет этот случай неопределенным.) Во всех случаях плохо полагаться на это поведение; однажды вы можете программировать для системы со скудной поддержкой С времени исполнения, или для внедренной системы, или где-то еще, где это будет по-другому. (В общем, выпадение в конце любой функции, не являющейся
void
— плохая мысль, которая может вести лишь к ошибочному коду.)

Возвращенное из

main
значение автоматически передается обратно системе, от которой родительский процесс может его впоследствии получить. Мы опишем, как это делается, в разделе 9.1.6.1 «Использование функций POSIX:
wait
и
waitpid
».

ЗАМЕЧАНИЕ. На системах GNU/Linux управляемая компилятором команда c99 запускает компилятор с соответствующими опциями, так что возвращаемое значение при выпадении из конца функции равно 0. Простой gcc этого не делает.

9.1.5.3. Функции завершения

Другим способом естественного завершения программы является вызов функций завершения. Стандарт С определяет следующие функции:

#include <stdlib.h> /* ISO С */

void exit(int status);

void _Exit(int status);

int atexit(void (*function)(void));

Эти функции работают следующим образом:

void exit(int status)

Эта функция завершает программу,

status
передается системе для использования родителем. Перед завершением программы
exit
вызывает все функции, зарегистрированные с помощью
atexit
, сбрасывает на диск и закрывает все открытые потоки <
stdio.h> FILE
* и удаляет все временные файлы, созданные
tmpfile
(см. раздел 12.3.2 «Создание и открытие временных файлов»). Когда процесс завершается, ядро закрывает любые оставшиеся открытыми файлы (которые были открыты посредством
open
,
creat
или через наследование дескрипторов), освобождает его адресное пространство и освобождает любые другие ресурсы, которые он мог использовать.
exit
никогда не возвращается.

void _Exit(int status)

Эта функция в сущности идентична функции POSIX

_exit
; мы на короткое время отложим ее обсуждение,

int atexit(void (*function)(void))

function
является указателем на функцию обратного вызова, которая должна вызываться при завершении программы,
exit
запускает функцию обратного вызова перед закрытием файлов и завершением. Идея в том, что приложение может предоставить одну или более функций очистки, которые должны быть запущены перед окончательным завершением работы. Предоставление функции называется ее регистрацией. (Функции обратного вызова для
nftw
обсуждались в разделе 8.4.3.2 «Функция обратного вызова
nftw
»; здесь та же идея, хотя
atexit
вызывает каждую зарегистрированную функцию лишь однажды.)

atexit
возвращает 0 при успехе или -1 при неудаче и соответствующим образом устанавливает
errno
.

Следующая программа не делает полезной работы, но демонстрирует, как работает

atexit
:

/* ch09-atexit.c --- демонстрация atexit.

Проверка ошибок для краткости опущена. */

/*

 * Функции обратного вызова здесь просто отвечают на вызов.

 * В настоящем приложении они делали бы больше. */

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

Матабар IV

Клеванский Кирилл Сергеевич
4. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар IV

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Геном хищника. Книга пятая

Гарцевич Евгений Александрович
5. Я - Легенда!
Фантастика:
рпг
фэнтези
попаданцы
6.00
рейтинг книги
Геном хищника. Книга пятая

Мечник Вернувшийся 1000 лет спустя. Том 2

Ткачев Андрей Юрьевич
2. Вернувшийся мечник
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Мечник Вернувшийся 1000 лет спустя. Том 2

Первый среди равных. Книга XIII

Бор Жорж
13. Первый среди Равных
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Первый среди равных. Книга XIII

Кожедуб

Бодрихин Николай Георгиевич
1216. Жизнь замечательных людей
Проза:
военная проза
5.00
рейтинг книги
Кожедуб

Заповедник гоблинов (сборник)

Саймак Клиффорд Дональд
Фантастика:
научная фантастика
5.00
рейтинг книги
Заповедник гоблинов (сборник)

Тринадцатый XI

NikL
11. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Тринадцатый XI

Последний Паладин. Том 4

Саваровский Роман
4. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 4

По осколкам твоего сердца

Джейн Анна
2. Хулиган и новенькая
Любовные романы:
современные любовные романы
5.56
рейтинг книги
По осколкам твоего сердца

Господин из завтра. Тетралогия.

Махров Алексей
Фантастика:
альтернативная история
8.32
рейтинг книги
Господин из завтра. Тетралогия.

Камень. Книга вторая

Минин Станислав
2. Камень
Фантастика:
фэнтези
8.52
рейтинг книги
Камень. Книга вторая

Зодчий. Книга III

Погуляй Юрий Александрович
3. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга III

Монстр из прошлого тысячелетия

Еслер Андрей
5. Соприкосновение миров
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Монстр из прошлого тысячелетия