viernes, 19 de diciembre de 2014

Manejo de grupos de procesos: setpgid y getpgid

Los grupos de procesos se usan para controlar a un conjunto de procesos asociados entre si a través de un identificador. De manera especifica se emplean para la distribución de señales. Así, si se le envía una señal al grupo de procesos cada uno de los miembros de ese grupo recibe dicha señal. El identificador del grupo de proceso recibe el nombre de pgid. 

Es importante saber que:
  • Todo proceso pertenece a un grupo de procesos.
  • En un grupo de procesos pueden haber uno o más procesos.
  • Cuando un proceso crea un hijo este hereda el PGID del padre.
  • Un proceso puede cambiarse de grupo usando la función setpgid()
  • Cualquier proceso puede saber a que grupo pertenece otro proceso si conoce el PID.


Asignar un PGID


int setpgid(pid_t pid, pid_t pgid);

La función setpgid asigna un pgid al proceso a un proceso. El parámetro 
pid indica el PID del proceso a modificarSi pid es cero, se emplea el PID del proceso en curso. 
Si pgid es cero, se emplea el PID del proceso especificado por pid. 
Si setpgid se utiliza para mover un proceso de un grupo de procesos a otro (como hacen algunos shells cuando crean tuberías), ambos grupos de procesos deben formar parte de la misma sesión. En este caso, pgid especifica el grupo de procesos existente en el que vamos a entrar, y el ID de sesión de ese grupo de procesos debe coincidir con el ID de sesión del proceso que quiere entrar. En  caso de éxito, setpgid y setpgrp devuelven cero. En caso de error. devuelven -1  y ponen un valor apropiado en errno

Obtener un PGID


La función getpgid devuelve el ID del grupo de proceso del especificado por pid. Si pid es cero, se emplea el PID del proceso en curso. getpgid devuelve un grupo de proceso si acaba bien; -1 en caso de error, y pone  un  valor apropiado en errno.

Enviar señales a un grupo de procesos

Se usa la función kill, con la salvedad que el pgid debe ser negativo. Esto para diferenciar del PID de algun proceso.
kill(-PGID, SIGNAL) // Note el signo negativo antes del PGID


Ejemplo #1:

En este ejemplo el proceso principal ( P1 ) creará 5 procesos hijos, los cuales heredarán su PID. 
Los hijos se dormirán al crearse y esperarán la señal del padre. 
El padre luego de crearlos duerme 2 segundos y luego le envía un mensaje a su propio grupo de procesos para despertar a todos los hijos.
Para ello usa kill(-getpgid(getpid()),SIGCONT);



#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <signal.h>

using namespace std;

// SIGCONT Signal handler
void h(int){}

int main(int argc, char *argv[])
{
    signal(SIGCONT,&h);
    int pid=0;
    cout<<"PID Padre="<<getpgid(getpid())<<endl;
    cout<<"PGID Padre="<<getpgid(getpid())<<endl;

    // El padre crea 5 hijos
    for (int i = 0; i < 5; ++i) {
        pid=fork();

        // Hijo
        if (pid==0){
            cout<<"Hijo "<<getpid()<<": Mi PGID es="<<getpgid(getpid())<<endl;

            // EL hijo se duerme
            sleep(300);

            // Cuando recibe la señal SIGCONT el hijo se despierta
            cout<<"Hijo "<<getpid()<<": Me despertaron"<<endl;
            exit(0);
        }
    }

   sleep(2);
   cout<<"Padre: envío SIGCONT al grupo "<<getpgid(getpid())<<endl;

   // Note que para enviar al grupo de procesos el valor
   // debe ser negativo
   kill(-getpgid(getpid()),SIGCONT);
}



Links de interés:


No hay comentarios:

Publicar un comentario