Outros Processos

Até agora, discutimos sobre os processos, sua criação, processos pai e filho, etc. A discussão será incompleta sem discutir outros processos relacionados, como o processo Órfão, o processo Zumbi e o processo Daemon.

Processo Órfão

Conforme indicado pelo nome, órfão implica processo sem pais. Quando executamos um programa ou aplicativo, o processo pai do aplicativo é o shell. Quando criamos um processo usando fork (), o processo recém-criado é o processo filho e o processo que criou o filho é o processo pai. Por sua vez, o processo pai disso é shell. Obviamente, o pai de todos os processos é o processo init (ID do processo → 1).

O cenário acima é um cenário normal, no entanto, o que acontece se o processo pai sair antes do processo filho. O resultado é que o processo filho agora se torna o processo órfão. Então, o que acontece com seu pai, seu novo pai é o pai de todos os processos, que nada mais é do que o processo init (ID do processo - 1).

Vamos tentar entender isso usando o exemplo a seguir.

/ * Nome do arquivo: órfão_processo.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;
}

Etapas de compilação e execução

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

Processo Zumbi

Em termos simples, suponha que você tenha dois processos, a saber, o processo pai e o filho. É responsabilidade do processo pai esperar pelo processo filho e, em seguida, limpar a entrada do processo filho da tabela de processos. E se o processo pai não estiver pronto para aguardar o processo filho e, nesse ínterim, o processo filho concluir seu trabalho e sair? Agora, o processo filho se tornaria o processo zumbi. Claro, o processo zumbi é limpo depois que o processo pai fica pronto.

Vamos entender isso com a ajuda de um exemplo.

/ * Nome do arquivo: 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;
}

Etapas de compilação e execução

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

Processo Daemon

Em termos simples, o processo que não tem nenhum shell ou terminal associado é conhecido como processo daemon. Por que isso é necessário? Esses são os processos executados em segundo plano para realizar ações em intervalos predefinidos e também responder a determinados eventos. O processo daemon não deve ter nenhuma interação com o usuário, pois é executado como um processo em segundo plano.

Os processos daemon internos do Linux geralmente terminam com a letra “d”, como Kernel Daemons (ksoftirqd, kblockd, kswapd, etc.), Impressão Daemons (cupsd, lpd, etc.), File Service Daemons (smbd, nmbd, etc.) , Daemons de banco de dados administrativo (ypbind, ypserv, etc.), Daemons de correio eletrônico (sendmail, popd, smtpd, etc.), Login remoto e Daemons de execução de comando (sshd, in.telnetd, etc.), Daemons de inicialização e configuração (dhcpd , udevd, etc.), processo init (init), cron daemon, atd daemon, etc.

Agora vamos ver como criar um processo daemon. A seguir estão as etapas -

Step 1- Crie um processo filho. Agora temos dois processos - o processo pai e o processo filho

Normalmente, a hierarquia do processo é SHELL → PROCESSO PAI → PROCESSO DA CRIANÇA

Step 2- Encerre o processo pai saindo. O processo filho agora se torna o processo órfão e é assumido pelo processo init.

Agora, a hierarquia é PROCESSO INIT → PROCESSO INFANTIL

Step 3- Chamar a chamada de sistema setsid () cria uma nova sessão, se o processo de chamada não for um líder de grupo de processo. Agora, o processo de chamada se torna o líder do grupo da nova sessão. Este processo será o único processo neste novo grupo de processos e nesta nova sessão.

Step 4 - Defina o ID do grupo de processo e o ID da sessão como PID do processo de chamada.

Step 5 - Feche os descritores de arquivo padrão (entrada padrão, saída padrão e erro padrão) do processo, pois o terminal e o shell agora estão desconectados do aplicativo.

/ * Nome do arquivo: 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