До сих пор мы обсуждали процессы, их создание, родительские и дочерние процессы и т. Д. Обсуждение будет неполным без обсуждения других связанных процессов, таких как процесс Orphan, процесс Zombie и процесс Daemon.
Сирота Процесс
Как видно из названия, сирота подразумевает процесс без родителей. Когда мы запускаем программу или приложение, родительским процессом для приложения является оболочка. Когда мы создаем процесс с использованием fork (), вновь созданный процесс является дочерним процессом, а процесс, который создал дочерний процесс, является родительским процессом. В свою очередь, родительским процессом является оболочка. Конечно, родителем всех процессов является процесс инициализации (ID процесса → 1).
Выше приведен обычный сценарий, однако, что произойдет, если родительский процесс завершится до дочернего процесса. В результате дочерний процесс теперь становится сиротским процессом. Тогда что касается его родителя, его новый родитель является родителем всех процессов, который является ничем иным, как процессом init (ID процесса — 1).
Давайте попробуем понять это, используя следующий пример.
/ * Имя файла: orphan_process.c * /
#include<stdio.h> #include<stdlib.h> int main() { int pid; system("ps -f"); pid = fork(); if (pid == 0) { printf("Child: pid is %d and ppid is %d\n",getpid(),getppid()); sleep(5); printf("Child: pid is %d and ppid is %d\n",getpid(),getppid()); system("ps -f"); } else { printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid()); sleep(2); exit(0); } return 0; }
Шаги компиляции и выполнения
UID PID PPID C STIME TTY TIME CMD 4581875 180558 0 0 09:19 ? 00:00:00 sh -c cd /home/cg/root/4581875; timeout 10s main 4581875 180564 180558 0 09:19 ? 00:00:00 timeout 10s main 4581875 180565 180564 0 09:19 ? 00:00:00 main 4581875 180566 180565 0 09:19 ? 00:00:00 ps -f Parent: pid is 180565 and ppid is 180564 UID PID PPID C STIME TTY TIME CMD 4581875 180567 0 0 09:19 ? 00:00:00 main 4581875 180820 180567 0 09:19 ? 00:00:00 ps -f Child: pid is 180567 and ppid is 180565 Child: pid is 180567 and ppid is 0
Зомби процесс
Проще говоря, предположим, что у вас есть два процесса, а именно родительский и дочерний процессы. Родительский процесс несет ответственность за ожидание дочернего процесса, а затем очистку записи дочернего процесса из таблицы процессов. Что если родительский процесс не готов ждать дочернего процесса, а тем временем дочерний процесс выполняет свою работу и завершается? Теперь дочерний процесс станет процессом зомби. Конечно, процесс зомби очищается после того, как родительский процесс становится готовым.
Позвольте нам понять это с помощью примера.
/ * Имя файла: zombie_process.c * /
#include<stdio.h> #include<stdlib.h> int main() { int pid; pid = fork(); if (pid == 0) { system("ps -f"); printf("Child: pid is %d and ppid is %d\n",getpid(),getppid()); exit(0); } else { printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid()); sleep(10); system("ps aux|grep Z"); } return 0; }
Шаги компиляции и выполнения
UID PID PPID C STIME TTY TIME CMD 4581875 184946 0 0 09:20 ? 00:00:00 sh -c cd /home/cg/root/4581875; timeout 10s main 4581875 184952 184946 0 09:20 ? 00:00:00 timeout 10s main 4581875 184953 184952 0 09:20 ? 00:00:00 main 4581875 184954 184953 0 09:20 ? 00:00:00 main 4581875 184955 184954 0 09:20 ? 00:00:00 ps -f Child: pid is 184954 and ppid is 184953
Демон Процесс
Проще говоря, процесс, который не имеет никакой связанной оболочки или терминала, называется процессом демона. Зачем это нужно? Это процессы, которые выполняются в фоновом режиме, чтобы выполнять действия с заданными интервалами, а также реагировать на определенные события. Процесс-демон не должен взаимодействовать с пользователем, поскольку он работает как фоновый процесс.
Внутренние процессы демона Linux обычно заканчиваются буквой «d», такие как демон ядра (ksoftirqd, kblockd, kswapd и т. Д.), Печать демонов (cupsd, lpd и т. Д.), Демоны файловой службы (smbd, nmbd и т. Д.) , Демоны административной базы данных (ypbind, ypserv и т. Д.), Демоны электронной почты (sendmail, popd, smtpd и т. Д.), Демоны удаленного входа в систему и выполнения команд (sshd, in.telnetd и т. Д.), Демоны загрузки и настройки (dhcpd , udevd и т. д.), процесс init (init), демон cron, демон atd и т. д.
Теперь давайте посмотрим, как создать процесс демона. Ниже приведены шаги —
Шаг 1 — Создайте дочерний процесс. Теперь у нас есть два процесса — родительский процесс и дочерний процесс
Обычно иерархия процессов: ОБОЛОЧКА → РОДИТЕЛЬСКИЙ ПРОЦЕСС → ДЕТСКИЙ ПРОЦЕСС
Шаг 2 — Завершить родительский процесс, выйдя. Дочерний процесс теперь становится сиротским процессом и переходит к процессу init.
Теперь, иерархия это INIT PROCESS → CHILD PROCESS
Шаг 3 — Вызов системного вызова setsid () создает новый сеанс, если вызывающий процесс не является лидером группы процессов. Теперь вызывающий процесс становится лидером группы нового сеанса. Этот процесс будет единственным процессом в этой новой группе процессов и в этом новом сеансе.
Шаг 4 — Установите идентификатор группы процессов и идентификатор сеанса в PID вызывающего процесса.
Шаг 5 — Закройте дескрипторы файлов по умолчанию (стандартный ввод, стандартный вывод и стандартная ошибка) процесса, поскольку терминал и оболочка теперь отключены от приложения.
/ * Имя файла: daemon_test.c * /
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> #include<string.h> int main(int argc, char *argv[]) { pid_t pid; int counter; int fd; int max_iterations; char buffer[100]; if (argc < 2) max_iterations = 5; else { max_iterations = atoi(argv[1]); if ( (max_iterations <= 0) || (max_iterations > 20) ) max_iterations = 10; } pid = fork(); // Unable to create child process if (pid < 0) { perror("fork error\n"); exit(1); } // Child process if (pid == 0) { fd = open("/tmp/DAEMON.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644); if (fd == -1) { perror("daemon txt file open error\n"); return 1; } printf("Child: pid is %d and ppid is %d\n", getpid(), getppid()); printf("\nChild process before becoming session leader\n"); sprintf(buffer, "ps -ef|grep %s", argv[0]); system(buffer); setsid(); printf("\nChild process after becoming session leader\n"); sprintf(buffer, "ps -ef|grep %s", argv[0]); system(buffer); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } else { printf("Parent: pid is %d and ppid is %d\n", getpid(), getppid()); printf("Parent: Exiting\n"); exit(0); } // Executing max_iteration times for (counter = 0; counter < max_iterations; counter++) { sprintf(buffer, "Daemon process: pid is %d and ppid is %d\n", getpid(), getppid()); write(fd, buffer, strlen(buffer)); sleep(2); } strcpy(buffer, "Done\n"); write(fd, buffer, strlen(buffer)); // Can't print this as file descriptors are already closed printf("DoneDone\n"); close(fd); return 0; }