Поиск по сайту:

Как убить зомби-процессы в Linux


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

Как состояния процесса работают в Linux

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

В каждой из структур таблицы процессов нет ничего особенного. Они содержат идентификатор процесса, несколько других элементов данных и указатель на блок управления процессом (PCB) для этого процесса.

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

Плата Linux содержит более 95 полей. Он определяется как структура с именем task_struct.h и имеет длину более 700 строк. Плата содержит следующие типы информации:

  • Состояние процесса. Состояния описаны ниже.
  • Номер процесса: его уникальный идентификатор в операционной системе.
  • Счетчик программ: когда этому процессу в следующий раз будет предоставлен доступ к ЦП, система будет использовать этот адрес для поиска следующей инструкции процесса, которая должна быть выполнена.
  • Регистры: список регистров ЦП, используемых этим процессом. Список может содержать аккумуляторы, индексные регистры и указатели стека.
  • Открыть список файлов: файлы, связанные с этим процессом.
  • Информация о планировании ЦП: используется для определения того, как часто и как долго процессорное время выделяется этому процессу. Приоритет процесса, указатели на очереди планирования и другие параметры планирования должны быть записаны в плате.
  • Информация об управлении памятью. Подробная информация о памяти, которую использует этот процесс, например начальный и конечный адреса памяти процесса и указатели на страницы памяти.
  • Информация о состоянии ввода-вывода: любые входные или выходные устройства, используемые процессом.

«Состояние процесса» может быть любым из следующих:

  • R: работающий или работающий процесс. Запуск означает, что он получает циклы ЦП и выполняется. Запускаемый процесс готов к запуску и ожидает освобождения слота ЦП.
  • S: Спящий процесс. Процесс ожидает завершения действия, например операции ввода или вывода, или освобождения ресурса.
  • D: Процесс постоянно находится в спящем состоянии. Он использует блокирующий системный вызов и не может продолжать работу, пока системные вызовы не будут завершены. В отличие от состояния Сон, процесс в этом состоянии не будет реагировать на сигналы до тех пор, пока системный вызов не будет завершен и процесс не вернется к выполнению.
  • T: процесс завершен (остановлен), так как он получил сигнал SIGSTOP. Он будет реагировать только на сигналы SIGKILL или SIGCONT, которые либо завершат процесс, либо предложат ему продолжить работу соответственно. Вот что происходит, когда вы переключаетесь с задач переднего плана (fg) на фоновые (bg) задачи.
  • Z: Зомби-процесс. Когда процесс завершается, он не просто исчезает. Он освобождает всю используемую им память и удаляет себя из памяти, но его запись в таблице процессов и плате остается. Его состояние установлено на EXIT_ZOMBIE, а его родительский процесс уведомлен (с помощью сигнала SIGCHLD) о завершении дочернего процесса.

В состоянии зомби родительский процесс вызывает одно из семейств функций wait() при создании дочернего процесса. Затем он ожидает изменения состояния дочернего процесса. Был ли дочерний процесс остановлен, продолжен или уничтожен по сигналу? Он завершился, выполнив естественное завершение своего кода?

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

Что вызывает зомби-процессы в Linux?

Плохо написанный родительский процесс может не вызывать функцию wait() при создании дочернего процесса. Это означает, что ничто не отслеживает изменения состояния в дочернем процессе, и сигнал SIGCHLD будет игнорироваться. Или, возможно, другое приложение влияет на выполнение родительского процесса либо из-за плохого программирования, либо из-за злого умысла.

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

Зомби используют немного памяти, но обычно они не представляют проблемы. Запись в таблице процессов небольшая, но, пока она не будет освобождена, идентификатор процесса нельзя использовать повторно. В 64-битной операционной системе это вряд ли вызовет какие-либо проблемы, потому что PCB намного больше, чем запись в таблице процессов.

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

Как удалить зомби-процессы

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

Единственное надежное решение — убить родительский процесс. Когда он завершается, его дочерние процессы наследуются процессом init, который является первым процессом, запущенным в системе Linux (его идентификатор процесса равен 1).

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

Введите следующее:

top

Эта система имеет восемь зомби-процессов. Мы можем перечислить их, используя команду ps и передав ее в egrep. Опять же, зомби-процессы имеют флаг состояния «Z», и вы обычно также видите «несуществующий».

Введите следующее:

ps aux | egrep "Z|defunct"

Перечислены зомби-процессы.

Это более удобный способ обнаружить идентификаторы процессов зомби, чем прокрутка назад и вперед по top. Мы также видим, что приложение под названием «badprg» породило этих зомби.

Идентификатор процесса первого зомби — 7641, но нам нужно найти идентификатор процесса его родительского процесса. Мы можем сделать это, снова используя ps. Мы воспользуемся параметром вывода (-o), чтобы указать ps отображать только идентификатор родительского процесса, а затем передать его с помощью ppid= флаг.

Процесс, который мы хотим найти, будет указан с помощью параметра -p (процесс), а затем передачи идентификатора процесса-зомби.

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

ps -o ppid= -p 7641

Нам сказали, что идентификатор родительского процесса — 7636. Теперь мы можем создать перекрестную ссылку, используя ps еще раз.

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

kill -SIGKILL 7636

В зависимости от владельца родительского процесса вам также может понадобиться использовать sudo.

Зомби не страшны…

… если они не в огромной орде. Не о чем беспокоиться, и простая перезагрузка уничтожит их.

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