Comunicación entre procesos y eficiencia energética.

@cmdearcos
Grupo TIECs

No se puede entender el mundo actual sin una comunicación robusta entre procesos. Podemos entender de forma genérica un proceso como un programa que se ejecuta en una CPU (sistema empotrado, smartphone, tablet, servidor …).

Hay veces que los procesos están en CPUs diferentes en cuyo caso es necesario un bus o una red de comunicaciones para que se puedan comunicar. Otras veces estos procesos están en la misma CPU y se comunican a través de la memoria (volátil o no) del dispositivo donde “corren”.

Para poder realizar estas comunicaciones hay una función en C vital para poder sincronizar adecuadamente estas comunicaciones. Esta función es int poll (struct pollfd fds[], nfsdt_t nfds, int timeout).

Cada vez que se llama a la función read para leer un descriptor de fichero esta devuelve de forma inmediata, haya datos o no que leer, los datos leídos. En el caso de estar leyendo un descriptor de fichero de una línea serie o de una pipe necesitamos saber cuando tenemos datos que leer y mientras no haya datos que leer el proceso se debe “bloquear” para no gastar CPU, y por tanto que el usuario no tenga sensación de perder velocidad, y no gastar energía innecesariamente.

Cuando se crea un servidor para comunicarse TCP/IP con un cliente se abre un socket y el servidor se queda esperando a que le llegue una petición. Si se utiliza la función read () el servidor jamás se quedará bloqueado esperando y por ello sería necesario crear un “bucle infinito” del que se saliera cuando llegara una petición con el consiguiente gasto de recursos y energía. Si en vez de read se utiliza las funciones recv (), el programa se queda bloqueado a la espera que lleguen datos (ojo, siempre y cuando se utilice la configuración adecuada: flags y/o fcntl).

¿Qué hace la función poll?. Proporciona a las aplicaciones un mecanismo para multiplexar entradas y salidas sobre una serie de descriptores de fichero. La función poll, como indicábamos antes, tiene la siguiente definición: int poll (struct pollfd fds[], nfsdt_t nfds, int timeout)

Para cada miembro del array apuntado por fds, poll() examina el descriptor de archivo para los acontecimientos especificados por nfds. La función poll() identifica estos descriptores de archivos en los que la aplicación puede leer o escribir datos.

La definición de la estructura pollfd es la siguiente:

struct pollfd {

     int   fd;       /* descriptor de fichero a comprobar */

     short events;   /* eventos por los que se quiere preguntar */

     short revents;  /* eventos que han sucedido */

   };

Es necesario pasar una estructura (por ello se pasa un array de estructura) por cada descriptor de fichero a controlar. Los eventos por los que se puede preguntar (y que pueden suceder) son los siguientes:

POLLIN

Todos los datos excepto los de alta prioridad se podrán leer sin bloqueo. Es equivalente a POLLRDNORM | POLLRDBAND

POLLRDNORM

Los datos normales (prioriddad=0) se porán leer sin bloqueo.

POLLRDBAND

Los datos de prioridad>0 se podrán leer sin bloqueo.

POLLPRI

Los datos de alta prioridad se podrán recibir sin bloqueo.

POLLOUT

Los datos normales (prioridad=0) se podrán escribir sin bloqueo.

POLLERR

Indica que un error se ha producido.

POLLHUP

Si han “colgado”. Por ejemplo alguien ha hecho close en el descriptor de fichero de una pipe.

POLLNVAL

El descripto de fichero pasado no pertenece a un fichero abierto.

En el miembro events se indica el evento por el que debe “saltar” la función poll () y en revents se indica cuales han sido las razones por las que ha “saltado” la función.

Siguiendo con las variables que se pasa a la función poll () decir que nfds es el número de elementos del array y que timeout es el tiempo de espera que tiene que esperar a que se produzca algunos de los eventos por los que se “pregunta”. En timeout pueden ir los siguientes datos:

= -1. El tiempo de espera es infinito. Hasta que no se produzca uno de los eventos no retornará la función poll.

= 0. En este caso retorna la función directamente sin espera.

> 0. En este caso la cifra indica será el tiempo de espera en milisegundos.

Gracias a esta función podemos realizar comunicaciones robustas entre procesos con el mínimo de gasto en CPU (evitando que los dispositivos “parezcan” lentos) y de energía.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *