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

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

Жанры

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

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

Шрифт:

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
извлекает из кода завершения номер сигнала.

Ниже приведена доработанная версия функции

main
из файла
fork-exec.c
. На этот раз программа вызывает функцию
wait
, чтобы дождаться завершения дочернего процесса, в котором выполняется команда
ls
.

int main {

 int child_status;

 /* Список аргументов, передаваемых команде ls. */

 char* arg_list[] = {

"ls", /* argv[0] —
имя программы. */

"-l",

"/",

NULL /* Список аргументов должен оканчиваться указателем

NULL. */

 };

 /* Порождаем дочерний процесс, который выполняет команду ls.

Игнорируем возвращаемый идентификатор дочернего процесса. */

 spawn("ls*, arg_list);

 /* Дожидаемся завершения дочернего процесса. */

 wait(&child_status);

 if (WTFEXITED(child_status));

 printf("the child process exited normally, with exit code %d\n",

WEXITSTATUS(child_status));

 else

printf("the child process exited abnormally\n");

 return 0;

}

Расскажем о других функциях семейства. Функция

waitpid
позволяет дождаться завершения конкретного дочернего процесса, а не просто любого. Функция
wait3
возвращает информацию о статистике использования центрального процессора завершившимся дочерним процессом. Функция
wait4
позволяет задать дополнительную информацию о том, завершения каких процессов следует дождаться.

3.4.3. Процессы-зомби

Если дочерний процесс завершается в то время, когда родительский процесс заблокирован функцией

wait
, он успешно удаляется и его код завершения передается предку через функцию
wait
. Но что произойдет, если потомок завершился, а родительский процесс так и не вызвал функцию
wait
? Дочерний процесс просто исчезнет? Нет, ведь в этом случае информация о его завершении (было ли оно аварийным или нет и каков код завершения) пропадет. Вместо этого дочерний процесс становится процессом-зомби.

Зомбиэто процесс, который завершился, но не был удален. Удаление зомби возлагается на родительский процесс. Функция

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

Что же всё-таки случится, если родительский процесс не удалит своих потомков? Они останутся в системе в виде зомби. Программа, показанная в листинге 3.6, порождает дочерний процесс, который немедленно завершается, тогда как родительский процесс берет минутную паузу, после чего тоже заканчивает работу, так и не позаботившись об удалении потомка.

Листинг 3.6. (zombie.c) Создание процесса-зомби

#include «stdlib.h>

#include <sys/types.h>

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

Сердце Дракона. Том 20. Часть 1

Клеванский Кирилл Сергеевич
20. Сердце дракона
Фантастика:
фэнтези
боевая фантастика
городское фэнтези
5.00
рейтинг книги
Сердце Дракона. Том 20. Часть 1

Холодный ветер перемен

Иванов Дмитрий
7. Девяностые
Фантастика:
попаданцы
альтернативная история
6.80
рейтинг книги
Холодный ветер перемен

Последнее желание

Сапковский Анджей
1. Ведьмак
Фантастика:
фэнтези
9.43
рейтинг книги
Последнее желание

Отмороженный 7.0

Гарцевич Евгений Александрович
7. Отмороженный
Фантастика:
рпг
аниме
5.00
рейтинг книги
Отмороженный 7.0

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Магия чистых душ 2

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.56
рейтинг книги
Магия чистых душ 2

Наследие Маозари 5

Панежин Евгений
5. Наследие Маозари
Фантастика:
фэнтези
юмористическое фэнтези
5.00
рейтинг книги
Наследие Маозари 5

Локки 4 Потомок бога

Решетов Евгений Валерьевич
4. Локки
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Локки 4 Потомок бога

Граф

Ланцов Михаил Алексеевич
6. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Граф

Миф об идеальном мужчине

Устинова Татьяна Витальевна
Детективы:
прочие детективы
9.23
рейтинг книги
Миф об идеальном мужчине

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Здравствуй, 1984-й

Иванов Дмитрий
1. Девяностые
Фантастика:
альтернативная история
6.42
рейтинг книги
Здравствуй, 1984-й

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Барон не играет по правилам

Ренгач Евгений
1. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон не играет по правилам