Есть два таких процесса: процесс-зомби и процесс-сирота, синий тощий гриб.

Linux
Есть два таких процесса: процесс-зомби и процесс-сирота, синий тощий гриб.

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

Если вы допустили ошибку, вы должны ее исправить, а программисты не боятся ошибок~

Я не знаю, если вы посмотрите на то, что вы сделали несколько лет назад, иногда у вас возникает чувство, это то, что я сделал? ? ?

Ну, я не любила себя в то время~

Давайте сразу к теме, какая связь между родительским и дочерним процессами?

обработать

Сначала поговорим о том, что такое процесс:

Давайте посмотрим, что говорит Baidu:

Недостаточно посмотреть на изображение, в системе windows оно выглядит так:

В системе Mac это выглядит так:

Вот как это выглядит в Linux: (можно немного длинного снимка экрана)

[root@iz2ze76ybn73dvwmdij06zz ~]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 5月20 ?       00:00:33 /usr/lib/systemd/systemd --system --deserialize 21
root         2     0  0 5月20 ?       00:00:00 [kthreadd]
root         3     2  0 5月20 ?       00:00:06 [ksoftirqd/0]
root         5     2  0 5月20 ?       00:00:00 [kworker/0:0H]
root         7     2  0 5月20 ?       00:00:02 [migration/0]
root         8     2  0 5月20 ?       00:00:00 [rcu_bh]
root         9     2  0 5月20 ?       00:30:40 [rcu_sched]
root        10     2  0 5月20 ?       00:00:17 [watchdog/0]
root        11     2  0 5月20 ?       00:00:16 [watchdog/1]
root        12     2  0 5月20 ?       00:00:02 [migration/1]
root        13     2  0 5月20 ?       00:00:03 [ksoftirqd/1]
root        15     2  0 5月20 ?       00:00:00 [kworker/1:0H]
root        17     2  0 5月20 ?       00:00:00 [kdevtmpfs]
root        18     2  0 5月20 ?       00:00:00 [netns]
root        19     2  0 5月20 ?       00:00:01 [khungtaskd]
root        20     2  0 5月20 ?       00:00:00 [writeback]
root        21     2  0 5月20 ?       00:00:00 [kintegrityd]
root        22     2  0 5月20 ?       00:00:00 [bioset]
root        23     2  0 5月20 ?       00:00:00 [kblockd]

Хорошо, каждая из вышеперечисленных строк — это описание процесса, давайте посмотрим на значение каждого параметра:

отметка описывать
UID ID пользователя
PID Идентификатор процесса
PPID идентификатор родительского процесса
C процесс в процентах от процессора
STIME время начала процесса
TTY Расположение терминала
TIME фактическое время использования процессора
CMD команда и параметры

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

Видно, что ни у одного процесса PID не равен 0, почему так? Черный знак вопроса?

0, как правило, является системным процессом, который является частью ядра и не выполняет никаких программ на диске.

fork

Процесс может создать новый процесс, вызвав функцию fork, а созданный процесс называется дочерним процессом.

Здесь следует отметить, что возвращаемое значение функции fork различно для родительского и дочернего процессов.

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

Проверим сказанное выше. Подготовьте сценарий.

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

int main(int argc, char const *argv[])
{

    pid_t p1 = fork();

    printf("%d\n",p1);

    if(p1 > 0)
    {
        printf("父进程 pid = %d, p1 = %d\n", getpid(), p1);
    }
    else
    {
        printf("子进程 pid = %d , ppid = %d, p1 = %d\n", getpid(), getppid(), p1);
    }

    return 0;
}

Запустите, чтобы увидеть результат:

[root@iz2ze76ybn73dvwmdij06zz ~]# ./fork2
10213
父进程 pid = 10212, p1 = 10213
0
子进程 pid = 10213 , ppid = 10212, p1 = 0

В приведенном выше небольшом примере мы видим, что возвращаемое значение родительского процесса является идентификатором дочернего процесса, а возвращаемое значение дочернего процесса равно 0.

потерянный процесс

Все мы знаем сирот. . .

Да, верно, осиротевшие процессы — это те же процессы, то есть процессы без родителя. Конечно, родительский процесс должен быть создан первым.Когда родительский процесс завершается, его дочерние процессы (один или несколько) становятся процессами-сиротами.

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

[root@iz2ze76ybn73dvwmdij06zz ~]# cat guer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>


int main()
{
    pid_t pid = fork();

    if (pid < 0) {
 perror("fork error;");
        exit(1);
    } else if (pid == 0) {
 sleep(5);
        printf ("子进程 : [ pid] = %d , 父进程 [ppid] = %d\n",getpid(),getppid());
        exit(0);

    } else if (pid > 0) {
 printf("我是父线程,我先退出一步~\n");
 exit(0);

    }
  return 0;
}

Выполните и посмотрите результат:

Подсчитано, что многие дети уже поняли это.После выхода родительского процесса дочерний процесс принимается процессом с идентификатором процесса 1. Это хороший результат, по крайней мере, им все еще кто-то управляет, и он разогрелся~ Процесс с идентификатором процесса 1 является процессом инициализации. Всякий раз, когда появляется процесс-сирота, процесс инициализации примет его и станет его родительским процессом. , чтобы позаботиться о нем для дальнейшей жизни как о сиротском процессе.

вред

Поскольку осиротевшие процессы берут на себя процесс init, они безвредны.

процесс зомби

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

Сначала подготовьте код:

[root@iz2ze76ybn73dvwmdij06zz ~]# cat zombie.c
  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <stdlib.h>

  int main()
  {
      pid_t pid;
      pid = fork();
     if (pid < 0)
     {
         perror("fork error:");
         exit(1);
     }
     else if (pid == 0)
     {
         printf("我是子进程,我要先退出一步了.\n");
  printf("子进程 id : %d\n" ,getpid());
         exit(0);
     } else {
         printf("我是父进程,我先睡2秒\n");
         printf("父进程 id : %d\n" ,getpid());

         sleep(2);

         while(2); //来个死循环,不退出的那种
    }


   return 0;
 }

Запустите и посмотрите результат:

Снова откройте терминал, чтобы увидеть результат процесса:

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

вред

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

иметь дело с

1. Убить родительский процесс

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

2. Родительский процесс вызывает ожидание или ожиданиеpid

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

3. Вилка дважды

Первая вилка: родительский процесс разветвляет дочерний процесс

Вторая вилка: дочерний процесс разветвляет дочерний процесс и завершает работу.

Затем процесс-внук берет на себя init, и когда процесс-внук завершается, init перезапускается.

Но перезапуск дочернего процесса должен выполняться сам по себе.

4. сигнальная функция

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

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

  • сигнал (SIGCLD, SIG_IGN)
  • сигнал (SIGCHLD, SIG_IGN)

Суммировать

Я думал, что это простой вопрос, но я не ожидал, что эта длина будет очень короткой, поэтому я чувствую, что программисты действительно ничего не могут сказать. Это просто и легко понять. Как только вы захотите углубиться, это займет определенное количество времени и усилий.

Ссылаться на:

  • «Расширенное программирование в среде UNIX (третье издание на китайском языке)»

  • http://suo.im/6tOqJz

  • http://suo.im/67gdou

Продолжайте обновлять, спасибо, что прочитали эту статью~

В этой статье используетсяmdniceнабор текста