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

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

В иде­а­ле такие про­цес­сы долж­ны быть уда­ле­ны из таб­ли­цы про­цес­сов после завер­ше­ния их выполнения.

Одна­ко по какой-то при­чине роди­тель­ский про­цесс не уда­лил его долж­ным образом.

Такие “нера­бо­та­ю­щие” про­цес­сы наблю­да­ют­ся в основ­ном у дочер­них процессов.

Роди­тель­ский про­цесс счи­ты­ва­ет ста­тус завер­ше­ния сво­е­го дочер­не­го процесса.

Это дела­ет­ся с помо­щью систем­но­го вызо­ва wait().

Как толь­ко это сде­ла­но, зом­би-про­цесс ликвидируется.

Что­бы луч­ше понять про­цесс обра­зо­ва­ния и устра­не­ния зом­би-про­цес­са, посмот­ри­те при­ве­ден­ную ниже схему.

Как работает состояние зомби-процесса

Итак, как рабо­та­ет состо­я­ние зомби-процесса?

В состо­я­нии зом­би-про­цес­са роди­тель вызы­ва­ет одну функ­цию wait() во вре­мя созда­ния дочер­не­го процесса.

Затем он ждет изме­не­ния состо­я­ния дочер­не­го процесса.

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

После это­го PCB (process control block) дочер­не­го про­цес­са уни­что­жа­ет­ся, а запись очищается.

Это про­ис­хо­дит очень быст­ро, и зом­би-про­цесс суще­ству­ет недолго.

Интересные факты о зомби-процессах

Неко­то­рые инте­рес­ные фак­ты о зом­би-про­цес­сах включают:

Вся систем­ная память и дру­гие ресур­сы, выде­лен­ные зом­би-про­цес­су, деал­ло­ки­ру­ют­ся при его завер­ше­нии с помо­щью систем­но­го вызо­ва exit().

Но его запись в таб­ли­це оста­ет­ся доступной.

Если роди­тель­ский про­цесс не запу­щен, нали­чие зом­би-про­цес­са озна­ча­ет ошиб­ку в опе­ра­ци­он­ной системе.

Это может не вызы­вать серьез­ных про­блем, если зом­би-про­цес­сов немного.

Но при боль­ших нагруз­ках при­сут­ствие зом­би-про­цес­сов может при­ве­сти к нехват­ке запи­сей в таб­ли­це процессов.

Мы рас­смот­рим опас­ность зом­би-про­цес­сов в сле­ду­ю­щем раз­де­ле этой статьи.

Роди­тель­ский про­цесс счи­ты­ва­ет ста­тус завер­ше­ния зом­би-про­цес­са с помо­щью функ­ции wait().

Затем зом­би-про­цесс уда­ля­ет­ся из системы.

После его уда­ле­ния запись в таб­ли­це про­цес­сов и иден­ти­фи­ка­тор про­цес­са могут быть исполь­зо­ва­ны повторно.

Если функ­ция wait() не исполь­зу­ет­ся роди­тель­ским про­цес­сом, зом­би оста­ет­ся в таб­ли­це процессов.

Послав сиг­нал SIGCHLD роди­тель­ско­му про­цес­су с помо­щью коман­ды kill, вы може­те уда­лить зом­би-про­цесс из системы.

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

Опасны ли зомби-процессы?

Зом­би-про­цес­сы исполь­зу­ют немно­го памя­ти, но обыч­но они не пред­став­ля­ют опасности.

Запись в таб­ли­це про­цес­сов неболь­шая, но вы не може­те исполь­зо­вать иден­ти­фи­ка­тор про­цес­са, пока зом­би-про­цесс не будет освобожден.

На 64-раз­ряд­ной ОС это не создаст про­бле­мы, пото­му что PCB боль­ше, чем запись таб­ли­цы процессов.

Огром­ное коли­че­ство зом­би-про­цес­сов может повли­ять на сво­бод­ную память, доступ­ную для дру­гих процессов.

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

В этом слу­чае остав­ши­е­ся иден­ти­фи­ка­то­ры про­цес­сов моно­по­ли­зи­ру­ют­ся зомби.

Если не оста­ет­ся ни одно­го иден­ти­фи­ка­то­ра про­цес­са, дру­гие про­цес­сы не могут быть запущены.

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

Что­бы убить зом­би-про­цесс, сна­ча­ла най­ди­те его.

Исполь­зуй­те при­ве­ден­ные ниже коман­ды для выяв­ле­ния зомби-процессов.

$ ps aux | egrep "Z|defunct"

Z, исполь­зу­е­мый в колон­ке STAT, и/или [defunct], исполь­зу­е­мый в послед­ней колон­ке выво­да, иден­ти­фи­ци­ру­ет зомби-процесс.

На самом деле, вы не може­те убить зом­би-про­цес­сы, так как они уже мертвы.

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

Исполь­зуй­те сле­ду­ю­щую коман­ду, что­бы узнать ID роди­тель­ско­го процесса.

$ ps -o ppid= <PID дочер­не­го процесса>.

Как толь­ко вы узна­е­те ID роди­тель­ско­го про­цес­са зом­би, отправь­те SIGCHLD роди­тель­ско­му процессу.

$ kill -s SIGCHLD <Роди­тель­ский PID>.

Если это не помог­ло уда­лить зом­би-про­цесс из таб­ли­цы про­цес­сов, вам нуж­но пере­за­пу­стить или убить его роди­тель­ский процесс.

Что­бы убить роди­тель­ский про­цесс зом­би, исполь­зуй­те сле­ду­ю­щий код.

$ kill -9 <Роди­тель­ский PID>

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

Это помо­жет вам обез­опа­сить себя.

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

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

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