В то время я только что написал официальный отчет, а учебные записи записали в то время, сейчас кажется, что в предыдущей записи есть ошибка, но я ее тогда не заметил. Спасибо, Лянсюй, за то, что открыл для себя и напомнил мне, когда я перепечатывал свою статью.
Если вы допустили ошибку, вы должны ее исправить, а программисты не боятся ошибок~
Я не знаю, если вы посмотрите на то, что вы сделали несколько лет назад, иногда у вас возникает чувство, это то, что я сделал? ? ?
Ну, я не любила себя в то время~
Давайте сразу к теме, какая связь между родительским и дочерним процессами?
обработать
Сначала поговорим о том, что такое процесс:
Давайте посмотрим, что говорит 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набор текста