Процессы и программы

Программа в Unix — это последовательность исполняемых инструкций на диске. Вы можете использовать команду size (показывает размеры секций в бинарном файле), чтобы получить очень поверхностную проверку структуры и требований к памяти программы, или использовать различные вызовы objdump для гораздо более подробного изучения. Такая исполняемая программа называется процессом. Процесс содержит код и начальные данные самой программы, а также фактическое состояние в текущий момент времени для текущего выполнения. А именно, это карта памяти и связанная с ней память (смотрите /proc/pid/maps), а также счетчик программ, регистры процессора, стек и, наконец, текущий корневой каталог, текущий каталог, переменные окружения и открытые файлы, а также ряд других вещей. Например, в современном Linux существуют управляющие группы (cgroups) и отношения пространств имен (namespaces).

В Unix процессы и программы — это две разные и независимые вещи. Вы можете запускать программу несколько раз одновременно. Например, вы можете запустить два экземпляра редактора vi, которые редактируют два разных текста. Программа и исходные данные одинаковы: это один и тот же редактор. Но состояние внутри процессов разное: текст, режим вставки, позиция курсора и т. д. отличаются. С точки зрения программиста, «код тот же, но значения переменных отличаются».

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

  • fork() — создание процесса. Новый процесс получает копию текущей программы, но с новым process id (pid). Родительскому процессу возвращается pid дочернего, тем самым строится дерево процессов.
  • exec() — загружает программу в существующий процесс на исполнение
  • wait() — ждет завершения дочернего процесса и позволяет сообщить родительскому процессу об успешном завершении дочернего
  • exit() — закрывает файлы, сокеты, освобождает память и затем завершает процесс. Код завершения возвращается родительскому процессу.

Дерево процессов в Linux можно посмотреть командой ps -ef --forest или утилитами pstree, tree, htop. Запустив ps -ef --forest в Ubuntu, мы можем увидеть, что он является дочерним процессом bash, который является дочерним от init, первого процесса системы:

Рождение и смерть процессов

Программа init с pid 1 не будет делать по сути ничего, кроме вызова wait(): она ждет завершения процессов и опрашивает их статус завершения, только чтобы их убрать из таблицы. Она также читает /etc/inittab и запускает программы, настроенные там. Когда что-то из inittab завершается и настроено на повторный запуск, оно будет перезапущено init.

Ядро Linux использует циклически замкнутый двухсвязный список записей struct task_struct для хранения дескрипторов процессов. Когда дочерний процесс завершается, пока родительский процесс еще не ожидает статуса завершения, exit() все равно освободит всю память, дескрипторы файлов и так далее, но task_struct  (в основном запись ps) не может быть обновлен. Может случиться так, что родительский процесс в какой-то момент времени придет к wait(), и тогда нам понадобится статус завершения, который хранится в поле в task_struct, поэтому нам нужно его сохранить. И к моменту, когда дочерний процесс уже мертв, запись в списке процессов не может очиститься, потому что статус завершения еще не был опрошен родителем. Unix называет такие процессы без памяти или других ресурсов — зомби.

Зомби

Зомби видны в списке процессов, когда генератор процесса (процесс, выполняющий fork) неисправен и не выполняет wait() должным образом. Они не занимают память или какие-либо другие ресурсы, кроме байтов, составляющих их task_struct.

Zombie Process

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

Характеристики зомби-процессов

  • Кратковременные: как правило, зомби-процессы недолговечны и существуют лишь недолгое время, пока родительский процесс не выполнит системный вызов wait() для получения статуса выхода.
  • Нефункциональные: зомби-процессы не используют ресурсы CPU, но все еще занимают место в таблице процессов.

Сироты

Возможен другой вариант. Родительский процесс завершается, в то время как дочерний процесс еще работает. Ядро установит ppid (родительский pid) таких дочерних процессов с мертвыми родителями в постоянное значение 1, или, другими словами: init наследует осиротевшие процессы. Когда дочерний процесс завершается, init будет wait() для статуса выхода дочернего процесса, как обычно. В этом случае появляется процесс-сирота.

Процесс становится сиротой непреднамеренно. Иногда намеренно становится сиротами из-за длительного времени выполнения назначенной задачи без внимания пользователя. У сиротского процесса есть управляющие терминалы.

Характеристики сиротских процессов

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

Демоны

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

Характеристики процессов демонов

  • Фоновая работа: демоны работают в фоновом режиме, выполняя задачи системного уровня без прямого вмешательства пользователя.
  • Долгосрочные: демоны предназначены для работы в течение длительных периодов времени, выполняя такие задачи, как обслуживание системы, сетевые службы или управление оборудованием.

Зомби

Сироты

Демоны

Зомби — это процесс, который выполнил свою задачу, но все равно показывает запись в таблице процессов. Дочерний процесс, который продолжает работать даже после того, как его родительский процесс завершается или завершается, не дожидаясь выполнения дочернего процесса, называется сиротой. Процесс-демон — это системный процесс, который всегда работает в фоновом режиме.
Состояния процесса-зомби всегда обозначаются буквой Z Процесс-сирота был создан неосознанно из-за сбоя системы. Состояние процесса-демона обозначается ? в поле столбца tty в выводе команды ps
Процесс-зомби имеет управляющие терминалы Процесс-сирота имеет управляющие терминалы. Процесс-демон не имеет управляющих терминалов.
Процесс-зомби считается мертвым, он не используется для системной обработки Процесс-сирота — это компьютерный процесс, даже после того, как его родитель завершает работу init, становится родительским и продолжает оставшуюся задачу. Программа, которая работает долгое время, делает их процессом-демоном и запускает его в фоновом режиме.
Процессы-зомби автоматически очищаются, когда родительский процесс считывает их статус выхода. Если процесс-зомби существует, вам может потребоваться перезапустить родительский процесс или, в крайнем случае, перезагрузить систему.
Чтобы удалить процесс-зомби, выполните команду kill.
Завершите процесс-сироту с помощью сигнала SIGHUP (1). Процесс-демон только при завершении работы системы или остановке сервиса.
[Посещений: 99, из них сегодня: 1]

Добавить комментарий