www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Мониторинг  

Какая задача мониторинга отнимает больше всего времени?

Многие системные администраторы тратят до 30% рабочего времени на рутину мониторинга. Но

 Читать далее...

Рынок труда  

Какие навыки вы хотите развивать в 2026 году?

Рынок труда меняется быстро. Еще вчера его называли рынком соискателей, а сегодня

 Читать далее...

Книжная полка  

От сисадмина до архитектора: книги, которые прокачают ваш стек в этом году

Новинки от издательства «БХВ» отличаются тем, что в них часто делается упор

 Читать далее...

Автоматизация  

Автоматизируем рутину: что реально работает?

Многие сисадмины автоматизировали что-то за последний год. Но далеко не все остались

 Читать далее...

Защита ИТ-системы  

Практическая защита: что вы внедрили и что мешает?

Какие меры безопасности реально внедрить в реальных условиях – и что не

 Читать далее...

Вопрос-ответ  

Обеспечиваем безопасную эксплуатацию базы данных

Что для вас чаще всего является причиной инцидентов с БД? Как вы

 Читать далее...

Книжная полка  

От «безопасного» Linux до Контролируемого взлома

Издательство «БХВ» продолжает радовать читателей интересными новинками и в наступившем году. Вы можете

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 13436
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 13544
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 11000
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 5895
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 6744
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 6617
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 9460
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 6071
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 6281
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 10444
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 13901
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 15371
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 17680
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 12537
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 10543
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 8749
Комментарии: 4
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 7356
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 6162
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 5784
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 6098
Комментарии: 1
Рецензия на книгу «MongoDB в действии»

 Читать далее...

Друзья сайта  

 «Убиваем» зомби

Архив номеров / 2004 / Выпуск №1 (14) / «Убиваем» зомби

Рубрика: Программирование /  Анализ данных

АНДРЕЙ УВАРОВ

«Убиваем» зомби

Практически в любой *nix-подобной операционной системе существует такое понятие, как «зомби». В качестве примера возмём Linux (2.4.20). Зомби – это процесс, завершивший своё выполнение, но не удалённый. Зомби практически не занимают никаких ресурсов, но поскольку они являются процессами, то занимают место в proc. Как известно, количество процессов в системе ограничено, и если текущее количество процессов максимально, то операционная система отказывает нам в создании новых процессов, мотивируя это временным отсутствием ресурсов. Таким образом и рождается проблема с зомби: их возникает так много, что в системе больше не могут создаваться новые процессы. Но чаще зомби встречаются поодиночке. С зомби сталкивался практически каждый программист, а число программ, в которых были или есть проблемы с зомби, настолько велико, что перечислить их все не представляется возможным. Вот только некоторые из них: lynx, xchat, links, stunnel, galeon, xinetd.

Процесс становится зомби тогда, когда он уже завершился, а в его родительском процессе не была вызвана функция wait. Функции wait, wait3, wait4 и waitpid предназначены для получения родительским процессом кода завершения его потомка. В случае если потомок уже завершился, все системные ресурсы, занимаемые процессом, будут освобождены, а функция немедленно возвратит значение pid потомка.

Для начала попробуем просто создать процесс-потомок:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main(){
    // С этого места начинает своё выполнение потомок
    pid_t chld_PID= fork();
    // Если chld_PID == 0, то текущий процесс – потомок
    if(chld_PID!= 0){
           printf("I"m a parent ");
    }else{
           printf("I"m a child ");
 
    return 0;
}

Вызовом fork создаётся копия текущего процесса. Выполнение нового процесса начинается с того места, где был произведён вызов fork. В случае благополучного создания нового процесса родителю fork возвращает pid потомка, а потомку возвращается ноль (значение 0 не является pid самого потомка, в Linux не существует процессов с pid, равным 0, для получения идентификатора текущего процесса необходимо использовать getpid). Это необходимо для того, чтобы процесс мог определить, является ли он родителем или потомком. В случае ошибки новый процесс не создаётся и возвращается -1.

Разобравшись с вызовом fork, попробуем создать одного зомби:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main(){
    pid_t chld_PID= fork();
    if(chld_PID!= 0){
           printf("I"m a parent ");
           // Остановим выполнение родителя до ввода символа
           getchar();
    }else{
           printf("I"m a child ");
    }
    return 0;
}

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

[dashin@dashin zombies]$ ps ax

  PID TTY      STAT   TIME COMMAND              
   1  ?        S      0:05 init                 
............................................... 
                                                
18730 pts/4    S      0:00 bash -rcfile .bashrc 
18767 pts/4    S      0:00 ./one_zomb           
18768 pts/4    Z      0:00 [one_zomb ]          
18864 pts/5    R      0:00 ps ax                

Значение поля STAT, равное Z, означает, что данный процесс и есть наш зомби. Но поодиночке зомби не страшны, поэтому модифицируем предыдущий пример:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

    int main(){
  pid_t our_child;
  while(our_child != -1){
      our_child= fork();
      if(our_child == 0){              
          return 0;
      }
  }
  getchar();
  return 0;
}

Итак, откомпилировав и выполнив текущий пример, мы получим максимальное количество процессов в системе. Если попробуем выполнить команду ps, то получим сообщение о невозможности выполнения нашей команды по известной нам причине (команда ps взята для примера, вызов практически любой команды будет завершён подобным образом).

[dashin@dashin  zombies]$ ps ax

bash: fork: Resource temporarily unavailable

Разобравшись с тем, что представляют собой зомби, стоит ознакомиться с некоторыми способами устранения создаваемой зомби проблемы.

Один из самых простых способов «убить» зомби – это «убить» их родителя. Если в системе «умирает» какой-либо процесс, то специальный демон init наследует всех потомков умершего процесса и удаляет их, если они уже завершили своё выполнение. Но у нас может не хватать прав на удаление родителя. Возможна ситуация, когда родитель выполняет какие-то необходимые нам действия, и, удалив его, можно потерять данные. Может быть множество причин, препятствующих этому способу. И нам останется только по очереди убивать всех зомби.

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

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
    
  
int main(){
  
   pid_t our_child;   
   our_child= fork();
   if(our_child == 0){
        return 0;
   }
   sleep(10);    
   wait();
   getchar();
   return 0;
}

Для наглядности этого примера выполним команду:

top -d 1

и параллельно выполним предварительно откомпилированный пример (см. рис.1).

Рисунок 1. Видимо, не только мы умеем порождать зомби

Рисунок 1. Видимо, не только мы умеем порождать зомби

Как и ожидалось, наш зомби, просуществовав около 10 секунд, будет удалён.

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

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

 
void killchld(){
   wait();
}
 
int main(){
   pid_t our_child;
   int i;
   signal(SIGCHLD, killchld);
   for(i=1;i< 0xFF;i++){
       our_child= fork();
       if(our_child == 0){            
          return 0;
       }
   }
   getchar();
   return 0;
}

В данном примере мы устанавливаем обработчик сигнала SIGCHLD вызовом signal. В качестве первого параметра signal имеет сигнал (точнее сказать – номер сигнала), который мы собираемся обрабатывать, а второй параметр – имя нашей функции-обработчика. Но здесь есть одна небольшая тонкость – если в качестве второго параметра установим SIG_IGN, то наши зомби будут умирать, но как сказано в man: «POSIX (3.3.1.3) не определяет, что случается при SIGCHLD, который установлен в SIG_IGN». То есть если у нас следующий пример будет работать в Linux – не значит, что он будет работать в BSD. Следовательно, таким способом пользоваться не рекомендуется.

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

 
int main(){
   pid_t our_child;
   signal(SIGCHLD, SIG_IGN);   // Так делать не стоит
   int i;
   for(i=1;i< 0xFF;i++){
       our_child= fork();
       if(our_child == 0){            
          return 0;
       }
   }
   getchar();
   return 0;
}

Способ избежать зомби в большинстве случаев зависит от ситуации. Важно помнить, что зомби нужны забота и внимание. И только тогда они не будут вас беспокоить.


Комментарии отсутствуют

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

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru