Другие процессы
До сих пор мы обсуждали процессы, их создание, родительские и дочерние процессы и т. Д. Обсуждение будет неполным без обсуждения других связанных процессов, таких как процесс-сирота, процесс-зомби и процесс-демон.
Сиротский процесс
Как видно из названия, сирота подразумевает процесс без родителей. Когда мы запускаем программу или приложение, родительским процессом для приложения является оболочка. Когда мы создаем процесс с помощью fork (), вновь созданный процесс является дочерним процессом, а процесс, создавший дочерний процесс, является родительским процессом. В свою очередь, его родительский процесс - оболочка. Конечно, родителем всех процессов является процесс init (ID процесса → 1).
Однако вышеописанный сценарий является обычным: что произойдет, если родительский процесс завершится раньше, чем дочерний процесс. В результате дочерний процесс теперь становится сиротским процессом. Тогда что насчет его родителя, его новый родительский элемент является родителем всех процессов, который является не чем иным, как процессом инициализации (идентификатор процесса - 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), демон cron, демон atd и т. д.
Теперь давайте посмотрим, как создать процесс-демон. Ниже приведены шаги -
Step 1- Создайте дочерний процесс. Теперь у нас есть два процесса - родительский и дочерний.
Обычно иерархия процессов: ОБОЛОЧКА → РОДИТЕЛЬСКИЙ ПРОЦЕСС → ДЕТСКИЙ ПРОЦЕСС.
Step 2- Завершить родительский процесс путем выхода. Дочерний процесс теперь становится сиротским процессом и передается процессу init.
Теперь иерархия - НАЧАЛО ПРОЦЕССА → ДЕТСКИЙ ПРОЦЕСС.
Step 3- Вызов системного вызова setsid () создает новый сеанс, если вызывающий процесс не является лидером группы процессов. Теперь вызывающий процесс становится лидером группы нового сеанса. Этот процесс будет единственным процессом в этой новой группе процессов и в этом новом сеансе.
Step 4 - Установите идентификатор группы процессов и идентификатор сеанса равным PID вызывающего процесса.
Step 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;
}
Parent: pid is 193524 and ppid is 193523
Parent: Exiting
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193526 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193528 193526 0 09:23 ? 00:00:00 grep main
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193529 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193531 193529 0 09:23 ? 00:00:00 grep main