Otros procesos

Hasta ahora, hemos discutido sobre los procesos, su creación, procesos padre e hijo, etc. La discusión estará incompleta sin discutir otros procesos relacionados, como el proceso Orphan, el proceso Zombie y el proceso Daemon.

Proceso huérfano

Como lo indica el nombre, huérfano implica proceso sin padres. Cuando ejecutamos un programa o aplicación, el proceso principal de la aplicación es shell. Cuando creamos un proceso usando fork (), el proceso recién creado es el proceso hijo y el proceso que creó al hijo es el proceso padre. A su vez, el proceso padre de esto es shell. Por supuesto, el padre de todos los procesos es init process (ID de proceso → 1).

Lo anterior es un escenario habitual, sin embargo, ¿qué sucede si el proceso padre sale antes que el proceso hijo? El resultado es que el proceso hijo ahora se convierte en el proceso huérfano. Entonces, ¿qué pasa con su padre, su nuevo padre es el padre de todos los procesos, que no es más que el proceso de inicio (ID de proceso - 1).

Intentemos entender esto usando el siguiente ejemplo.

/ * Nombre de archivo: 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;
}

Pasos de compilación y ejecución

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

Proceso Zombie

En términos simples, suponga que tiene dos procesos, a saber, el proceso principal y el secundario. Es responsabilidad del proceso padre esperar al proceso hijo y luego limpiar la entrada del proceso hijo de la tabla de procesos. ¿Qué sucede si el proceso padre no está listo para esperar al proceso hijo y, mientras tanto, el proceso hijo hace su trabajo y sale? Ahora, el proceso hijo se convertiría en el proceso zombi. Por supuesto, el proceso zombie se limpia una vez que el proceso principal está listo.

Entendamos esto con la ayuda de un ejemplo.

/ * Nombre de archivo: 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;
}

Pasos de compilación y ejecución

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

Proceso de demonio

En términos simples, el proceso que no tiene ningún shell o terminal asociado se conoce como proceso demonio. ¿Por qué esto es necesario? Estos son los procesos que se ejecutan en segundo plano para realizar acciones a intervalos predefinidos y también responder a ciertos eventos. El proceso del demonio no debería tener ninguna interacción del usuario, ya que se ejecuta como un proceso en segundo plano.

Los procesos internos del demonio de Linux generalmente terminan con la letra "d", como Kernel Daemons (ksoftirqd, kblockd, kswapd, etc.), Printing Daemons (cupsd, lpd, etc.), File Service Daemons (smbd, nmbd, etc.) , Demonios de bases de datos administrativas (ypbind, ypserv, etc.), demonios de correo electrónico (sendmail, popd, smtpd, etc.), demonios de inicio de sesión remoto y ejecución de comandos (sshd, in.telnetd, etc.), demonios de arranque y configuración (dhcpd , udevd, etc.), proceso de inicio (init), demonio cron, demonio atd, etc.

Ahora veamos cómo crear un proceso de demonio. Los siguientes son los pasos:

Step 1- Crear un proceso hijo. Ahora tenemos dos procesos: el proceso padre y el proceso hijo

Por lo general, la jerarquía del proceso es SHELL → PROCESO DE LOS PADRES → PROCESO DEL NIÑO

Step 2- Termine el proceso principal saliendo. El proceso hijo ahora se convierte en el proceso huérfano y es asumido por el proceso init.

Ahora, la jerarquía es PROCESO INICIAL → PROCESO INFANTIL

Step 3- La llamada al sistema setsid () crea una nueva sesión, si el proceso que llama no es un líder de grupo de procesos. Ahora el proceso de llamada se convierte en el líder de grupo de la nueva sesión. Este proceso será el único proceso en este nuevo grupo de procesos y en esta nueva sesión.

Step 4 - Configure el ID del grupo de procesos y el ID de la sesión en el PID del proceso de llamada.

Step 5 - Cierre los descriptores de archivo predeterminados (entrada estándar, salida estándar y error estándar) del proceso, ya que el terminal y el shell ahora están desconectados de la aplicación.

/ * Nombre de archivo: 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