Poniendo El Proceso en Background

La subrutina become_daemon utiliza una técnica estandard en UNIX para poner procesos en background y disociarlos de su terminal.

sub become_daemon {
  die "Can't fork" unless defined (my $child = fork);
  exit 0 if $child;             # parent dies;
  setsid();                     # become session leader
  open(STDIN, "</dev/null");
  open(STDOUT,">/dev/null");
  open(STDERR,">&STDOUT");
  chdir '/';                    # change working directory
  umask(0);                     # forget file mode creation mask
  $ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin';
  $SIG{CHLD} = \&reap_child;
  return $$;
}

  1. Se hace un fork y el padre termina. Es el hijo el que continúa con la ejecución del programa.
  2. El proceso hijo arranca una nueva sesión llamando a setsid .

    Una sesión es un conjunto de procesos que comparten la misma terminal. En cualquier instante solo un grupo de procesos del conjunto tiene el privilegio de leer/escribir en la terminal. Decimos que estos procesos están en foreground y que el resto de los procesos están en background. Estos procesos en foreground juegan un papel especial en el manejo de señales generadas por los caracteres de entrada.

    Un grupo de sesión está relacionado pero no es exactamente lo mismo que un grupo de procesos. Un grupo de procesos es un conjunto de procesos que han sido lanzados por un padre común y se caracterizan mediante un entero (el PID del grupo) que es el PID del ancestro común.

    Cuando una terminal resulta asociada con una sesión, el grupo de procesos en foreground se establece como el grupo de procesos del lider de sesión. La terminal asociada con una sesión es conocida como terminal controlada. La terminal controlada es heredada por los hijos generados durante un fork. La terminal controlada para una sesión es asignada por el lider de sesión de una manera que es dependiente de la implementación. Los procesos normales no pueden modificar la terminal controlada; solo el proceso lider puede hacerlo.

    Si un proceso pertenece al grupo de procesos en foreground de su terminal puede leer y escribir en ella; sin embargo, un proceso en el grupo de procesos en background que intente leer o escribir en su terminal dará lugar a la generación de una señal a su grupo de procesos14.1. Las señales son SIGTTIN (21) para la lectura y SIGTTOU (22) para la escritura. SIGTTIN = SIG-TT-IN.

    La llamada a setsid crea una nueva sesión y un nuevo grupo de procesos. El efecto total es que el proceso hijo es ahora independiente de la shell y de la terminal. Con esto conseguimos que la finalización de la shell o el cierre de la terminal no conlleven la muerte del proceso.

    La llamada a setsid falla si el proceso era ya un lider de sesión. Esta es una de las razones para que hayamos matado al padre y confiado la ejecución del programa al hijo.

  3. Reabrimos STDIN STDOUT y STDERR al dispositivo nulo. Se completa de esta forma el paso anterior, impidiendo el acceso del daemon a la terminal y que sus salidas se mezclen con las de la terminal.

  4. Se pone como directorio actual la raíz

  5. Se pone la máscara de creación de ficheros a un valor explícito. en este caso 0. Es conveniente que el daemon controle claramente los permisos de los ficheros que cree.

    La máscara de usuario es usada por open para establecer los permisos iniciales de un fichero recién creado. Los permisos presentes en la máscara se desactivan. La siguiente sesión con el depurador muestra el funcionamiento:

    pp2@nereida:~$ perl -wde 0
    main::(-e:1):   0
      DB<1> umask 0000
      DB<2> open f, '>/tmp/tutu' # Open por defecto usa un mode 0666
      DB<3> !!ls -ltr /tmp | tail -1 # 0666 and not 000 = 0666
    -rw-rw-rw- 1 pp2 pp2     0 2008-05-14 10:01 tutu
      DB<4> umask 0777  # 0666 and not 0777 = 000
      DB<5> open f, '>/tmp/tutu1'
      DB<6> !!ls -ltr /tmp | tail -1
    ---------- 1 pp2 pp2     0 2008-05-14 10:01 tutu1
      DB<7> umask 0022
      DB<8> open f, '>/tmp/tutu2'
      DB<9> !!ls -ltr /tmp | tail -1 # 0666 and not 0022 = 0644
    -rw-r--r-- 1 pp2 pp2     0 2008-05-14 10:02 tutu2
      DB<10> umask 0027
      DB<11> open f, '>/tmp/tutu3' # 0666 and not 0027 = 0640
      DB<12> !!ls -ltr /tmp | tail -1
    -rw-r----- 1 pp2 pp2     0 2008-05-14 10:06 tutu3
    

  6. Se pone el PATH al mínimo número de directorios necesario

  7. Se retorna el nuevo identificador del proceso. Puesto que es el hijo el que continúa con la ejecución del programa el identificador del proceso ha cambiado.

Casiano Rodríguez León
Licencia de Creative Commons
Programación Distribuida y Mejora del Rendimiento
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=44.
2012-06-19