DE LOS NAMESPACES EN LINUX (I)

EL NAMESPACE DE PIDS

El identificador de proceso (PID) es un número empleado por el Kernel para referirse de manera unívoca a los procesos que corren en un máquina. Los PIDs se emplean para interactuar con los procesos, por ejemplo, mediante el envío de señales o su repriorización con la utilidad nice. Cada proceso tiene asignado un PID que es único (ningún otro proceso activo puede tener el mismo PID) No obstante, con la introducción del namespace de PIDs (en Linux 2.6.24) esta situación ha variado. En un ejemplo en Perl:

# Un proceso clona un proceso hijo y espera su terminación.

use strict;

use Eixo::Zone; 

my $pid_hijo = Eixo::Zone->init(

    init=>sub {
        print “Soy el proceso hijo y (en mi namespace) tengo pid ” . &Eixo::Zone::getPid() . “\n“;
        sleep (1);
        exit (0);
    }

);

print “Soy el proceso padre y mi hijo tiene pid $pid_hijo \n“;

waitpid($pid_hijo, 0);

Salida:

Soy el proceso padre y mi hijo tiene pid 26708

Soy el proceso hijo y (en mi namespace) tengo pid 1

¿QUÉ HA PASADO?

A) CREACIÓN TRADICIONAL DE UN PROCESO HIJO

Empecemos por una creación de hijo normal a través de fork. 

Fork tradicional de un procesoEl proceso hijo es una copia exacta de su padre que se inicia desde la llamada a fork().

B) CREACIÓN DE UN PROCESO HIJO A TRAVÉS DE CLONE

En el ejemplo de Perl, se ha empleado clone. Esta llamada, entre otras cosas, nos permite crear nuevos namespaces a la hora de producir un proceso hijo. Esto es, indicamos en la creación del hijo qué namespaces propios debe tener Si le indicamos que cree su propio namespace para PIDs: 

Llamada a clone y creación de un namespace nuevo de pidsAhora, nuestro proceso hijo “vive” en su propio namespace y tiene, por tanto, dos PIDs: uno en el espacio de su padre y otro en el suyo propio. Para conocer su PID, un proceso realiza una llamada al Kernel: getpid(). Si el proceso hijo llama al Kernel para pedir su pid:

print “Soy el proceso hijo y (en mi namespace) tengo pid ” . &Eixo::Zone::getPid() . “\n“;

El Kernel devuelve el PID que el hijo tiene dentro de su namespace (PID = 1)

Es decir: El kernel contextualiza las llamadas de los procesos de acuerdo a su namespace El proceso padre quiere esperar a que el proceso hijo termine su ejecución. Para ello, emplea la llamada a waitpid.

waitpid ($pid_hijo, 0);

Espera mientras no termina el proceso hijo ¿Qué PID empleará? Desde su punto de vista (desde su namespace) el PID del proceso hijo será el que recibió en la llamada a clone y ese será el que emplee para esperar.

PROCESOS CON PID = 1

El primer proceso que entra en un namespace de PIDs recibirá (dentro del espacio) el PID 1. Esto tiene importancia, así:

  • El proceso se comporta, en cierto sentido, como el init del sistema
  • Los procesos huérfanos dentro del namespace creado serán adoptados por este proceso y no por el init del sistema
  • La llamada getppid(), desde dentro del namespace, para obtener el padre de este proceso devolverá siempre 0.
  • Este proceso puede “matarse” normalmente terminando todo su árbol de procesos (y el namespace)