Вход/Регистрация
Программирование для Linux. Профессиональный подход
вернуться

Самьюэл Алекс

Шрифт:

void handler(int signal_number) {

 ++sigusr1_count;

}

int main {

 struct sigaction sa;

 memset(&sa, 0, sizeof(sa));

 sa.sa_handler = &handler;

 sigaction(SIGUSR1, &sa, NULL);

 /* далее идет основной текст. */

 /* ... */

 printf("SIGUSR1 was raised %d times\n", sigusr1_count);

 return 0;

}

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

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

exit
, либо функция
main
заканчивается. У каждого процесса есть код завершения — число, возвращаемое родительскому процессу. Этот код передается в качестве аргумента функции
exit
или возвращается функцией
main
.

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

SIGBUS
,
SIGSEGV
и
SIGFPE
. Есть сигналы, явно запрашивающие прекращение работы процесса. В частности, сигнал
SIGINT
посылается, когда пользователь нажимает <Ctrl+C>. Сигнал
SIGTERM
посылается процессу командной
kill
по умолчанию. Если программа вызывает функцию
abort
, она посылает сама себе сигнал
SIGABRT
. Самый "могучий" из всех сигналов —
SIGKILL
: он приводит к безусловному уничтожению процесса и не может быть ни блокирован, ни обработан.

Любой сигнал можно послать с помощью команды

kill
, указав дополнительный флаг. Например, чтобы уничтожить процесс, послав ему сигнал
SIGKILL
, воспользуйтесь следующей командой:

% kill -KILL идентификатор_процесса

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

kill
. Ее первым аргументом является идентификатор процесса. Второй аргумент — номер сигнала (стандартному поведению команды
kill
соответствует сигнал
SIGTERM
). Например, если переменная
child_pid
содержит идентификатор дочернего процесса, то следующая функция, вызываемая из родительского процесса, вызывает завершение работы потомка:

kill(child_pid, SIGTERM);

Для использования функции

kill
необходимо включить в программу файлы
<sys/types.h>
и
<signal.h>
.

По существующему соглашению код завершения указывает на то, успешно ли выполнилась программа. Нулевой код говорит о том, что все в порядке, ненулевой код свидетельствует об ошибке. В последнем случае конкретное значение кода может подсказать природу ошибки. Подобным образом функционируют все компоненты GNU/Linux. Например, на это рассчитывает интерпретатор команд, когда в командных сценариях вызовы программ объединяются с помощью операторов

&&
(логическое умножение) и
||
(логическое сложение) Таким образом, функция
main
должна явно возвращать 0 при отсутствии ошибок.

Помните о следующем ограничении: несмотря на то что тип параметра функции

exit
, как и тип возвращаемого значения функции
main
, равен
int
, операционная система Linux записывает код завершения лишь в младший из четырех байтов. Это означает, что значение кода должно находиться в диапазоне от 0 до 127. Коды, значение которых больше 128, интерпретируются особым образом: когда процесс уничтожается вследствие получения сигнала, его код завершения равен 128 плюс номер сигнала.

3.4.1. Ожидание завершения процесса

Читатели, запускавшие программу

fork-exec
(см. листинг 3.4), должно быть, обратили внимание на то, что вывод команды
ls
часто появляется после того, как основная программа уже завершила свою работу. Это связано с тем, что дочерний процесс, в котором выполняется команда
ls
, планируется независимо от родительского процесса. Linux — многозадачная операционная система, процессы в ней выполняются одновременно, поэтому нельзя заранее предсказать, кто — предок или потомок — завершится раньше.

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

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

3.4.2. Системные вызовы wait

Самая простая функция в семействе называется

wait
. Она блокирует вызывающий процесс до тех пор, пока один из его дочерних процессов не завершится (или не произойдет ошибка). Код состояния потомка возвращается через аргумент, являющийся указателем на целое число. В этом коде зашифрована различная информация о потомке. Например, макрос
WEXITSTATUS
возвращает код завершения дочернего процесса. Макрос
WIFEXITED
позволяет узнать, как именно завершился процесс: обычным образом (с помощью функции
exit
или оператора
return
функции
main
) либо аварийно вследствие получения сигнала. В последнем случае макрос
WTERMSIG
извлекает из кода завершения номер сигнала.

  • Читать дальше
  • 1
  • ...
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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