Altri processi

Finora, abbiamo discusso dei processi, della sua creazione, dei processi padre e figlio, ecc. La discussione sarà incompleta senza discutere altri processi correlati, come il processo Orphan, il processo Zombie e il processo Daemon.

Processo orfano

Come indicato dal nome, orfano implica un processo senza genitori. Quando eseguiamo un programma o un'applicazione, il processo principale dell'applicazione è shell. Quando creiamo un processo usando fork (), il processo appena creato è il processo figlio e il processo che ha creato il figlio è il processo genitore. A sua volta, il processo genitore di questo è shell. Ovviamente, il genitore di tutti i processi è init process (Process ID → 1).

Quanto sopra è uno scenario normale, tuttavia, cosa succede se il processo genitore esce prima del processo figlio. Il risultato è che il processo figlio ora diventa il processo orfano. Allora per quanto riguarda il suo genitore, il suo nuovo genitore è il genitore di tutti i processi, che non è altro che init process (Process ID - 1).

Cerchiamo di capirlo usando il seguente esempio.

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

Fasi di compilazione ed esecuzione

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 Zombie

In termini semplici, supponi di avere due processi, vale a dire il processo genitore e figlio. È responsabilità del processo padre attendere il processo figlio e quindi ripulire la voce del processo figlio dalla tabella dei processi. Cosa succede se il processo genitore non è pronto ad attendere il processo figlio e nel frattempo il processo figlio svolge il suo lavoro ed esce? Ora, il processo figlio diventerebbe il processo zombie. Naturalmente, il processo zombie viene ripulito dopo che il processo genitore è pronto.

Cerchiamo di capirlo con l'aiuto di un esempio.

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

Fasi di compilazione ed esecuzione

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

In termini semplici, il processo che non ha alcuna shell o terminale associato è noto come processo daemon. Perché è necessario? Questi sono i processi che vengono eseguiti in background per eseguire azioni a intervalli predefiniti e rispondere anche a determinati eventi. Il processo daemon non dovrebbe avere alcuna interazione da parte dell'utente, poiché viene eseguito come processo in background.

I processi del demone Linux interno di solito terminano con la lettera "d" come i demoni del kernel (ksoftirqd, kblockd, kswapd, ecc.), I demoni di stampa (cupsd, lpd, ecc.), I demoni del servizio file (smbd, nmbd, ecc.) , Daemon di database amministrativi (ypbind, ypserv, ecc.), Daemon di posta elettronica (sendmail, popd, smtpd, ecc.), Daemon di accesso remoto ed esecuzione di comandi (sshd, in.telnetd, ecc.), Daemon di avvio e configurazione (dhcpd , udevd, ecc.), init process (init), cron daemon, atd daemon, ecc.

Vediamo ora come creare un processo daemon. Di seguito sono riportati i passaggi:

Step 1- Crea un processo figlio. Ora abbiamo due processi: il processo genitore e il processo figlio

Di solito la gerarchia del processo è SHELL → PARENT PROCESS → CHILD PROCESS

Step 2- Termina il processo genitore uscendo. Il processo figlio ora diventa il processo orfano e viene rilevato da init process.

Ora, la gerarchia è INIT PROCESS → CHILD PROCESS

Step 3- La chiamata alla chiamata di sistema setsid () crea una nuova sessione, se il processo chiamante non è un leader del gruppo di processi. Ora il processo di chiamata diventa il capogruppo della nuova sessione. Questo processo sarà l'unico processo in questo nuovo gruppo di processi e in questa nuova sessione.

Step 4 - Impostare l'ID del gruppo di processi e l'ID di sessione su PID del processo chiamante.

Step 5 - Chiudere i descrittori di file predefiniti (input standard, output standard e errore standard) del processo poiché il terminale e la shell sono ora scollegati dall'applicazione.

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