Usuario :
Clave :
[ Recuperar mi clave ] [ Crear una cuenta ]
Jonathan Makuc, Universidad Diego Portales
  Suscripción   RSS







Semáforos en PHP
Por Jonathan Makuc, última modifiación: 01 de Noviembre de 2008 04:51, leído 12470 veces.
Tags: Manuales

La concurrencia en informática ha sido tema recurrente de preocupación, y es un punto muy importante en sistemas web dado que un sitio popular puede tener muchos visitantes literalmente al mismo tiempo.

PHP provee de forma nativa funciones que permiten utilizar los semáforos, memoria compartida e IPC de System V; disponibles en sistemas operativos Linux, Unix, FreeBSD y MacOSX entre otros, no disponible en Windows. A continuación un pequeño tutorial de su uso.

 

Teoría de semáforos

Los semaforos son elementos de sincronización que permiten sincronizar el uso de un recurso compartido en un sistema computacional. En otras palabras, permiten asegurar que solo un número determinado de procesos (visitantes en el caso de un sitio web) pueda acceder a un recurso simulatáneamente, por ejemplo, realizar una operación de cuenta corriente, aumentar un contador de visitas, etc. Estos son implementados por definición en el sistema operativo.

Aquella porcion del código que puede provocar problemas cuando se accede por varios procesos al mismo tiempo se denomina region crítica.

Antes de entrar a una region crítica, el proceso debe solicitar autorización al semáforo para poder pasar adquiriendo el semáforo (en la literatura conocido como el método P() o down() ). Al terminar la región crítica, el proceso libera el semáforo (conocido formalmente como el método V() o up() ). La analogía que se suele utilizar es que antes de entrar a la región crítica, el proceso intenta de tomar "una banderita" del semáforo; si hay banderitas disponibles entonces el proceso continua su ejecución, de lo contrario espera hasta que el o los otros procesos que pasaron antes "liberen una banderita", continuando la ejecución.

 

Semáforos en PHP

sem_get: función que permite crear un semáforo en el sistema operativo o recuperar uno existene. Recibe como parámetro obligatorio un INT con el identificador único del semáforo en el sistema. Como parámetros opcionales tenemos el valor inicial del semáforo (por defecto 1), permisos de acceso (en permisos unix) y un booleano para autoliberación al terminar el script.

$sem = sem_get(ftok(__FILE__, chr($id), 1);

Este comando de ejemplo creará un semáforo en el sistema inicializándolo en 1 (con 1 "banderita"), es decir, que solo un proceso a la vez podrá estar en la región crítica. Como identificador hemos usado la funcion ftok, la cual entrega un número válido para usarse en el sistema IPC de System V, tomando como parámetros un path completo a un archivo, y un identificador de proyecto de 1 caracter (de ahí el uso de la funcion chr para convertir $id en un char, notando que $id debe ser estrictamente numérico).

La primera vez que se invoque a este comando, se creará el semáforo en el sistema. Desde la segunda en adelante se utilizará el semáforo existente. Aunque el valor de $sem sea distinto, el semáforo en el sistema operativo es el mismo..

Un ejemplo de aplicacion del anterior semáforo podría ser en un sistema que maneja múltiples proyectos donde se quiere tener un semáforo por proyecto, entonces se conjuga el nombre del script que realiza accion con el identificador del proyecto (id de la tabla, por ejemplo).

 

sem_acquire: adquiere un semáforo ya creado en el sistema recibiendo como parámetro el identificador entregado por sem_get. Si no existe, el comando lanza un warning ad-hoc y retorna FALSE.

sem_acquire($sem);

De existir el semáforo indicado, esta instrucción bloquea la ejecución del script hasta que un proceso realize una liberación al semáforo.

 

sem_release: realiza una liberación al semáforo indicado. Nótese que el proceso no tiene porque haber adquirido antes este semáforo. Este comportamiento es necesario para resolver muchos problemas de sincronización.

sem_release($sem);

 

sem_remove: elimina un semáforo del sistema operativo, haciéndolo inaccesible en el futuro.

sem_remove($sem);

 

Veamos un ejemplo completo.

Supongamos que necesitamos escribir a un archivo de log las actividades de los visitantes de un sitio. Si solo invocáramos a fopen y fwrite, entonces puede suceder que 2 procesos intercalen la información en el archivo, porque ninguno está esperando que el otro termine. Este es un problema clásico de sincronización. A continuación un buen método de log a archivo para PHP.

 

function log($mensaje) {

 

  global $pathArchivoLog; 

  $sem = sem_get(ftok($pathArchivoLog, "W"), 1);
  sem_acquire($sem);

 

  $f = fopen($pathArchivoLog, "a");
  fwrite($f, $mensaje);
  fclose($f);

 

  sem_release($sem);

}

Aqui tenemos un semáforo cuyo ID se forma por el ftok del archivo log, contenido en la variable $pathArchivoLog, más la letra W como identificador de proyecto (W por write, elección arbitraria), que ha sido inicializado en 1. Se adquiere el semáforo (asegurándo la atomicidad), se abre el archivo en modo "append" y se escriben los datos. Se libera el semáforo para que el siguiente proceso pueda logear.

Un ejemplo más práctico para poder probar rápidamente de forma empírica los semáforos de PHP, puede ser el código a continuación ejecutado de 2 browsers simultáneamente. Nótese que se requieren 2 computadores para la prueba, puesto que Apache suele agrupar solicitudes de un mismo IP y encolarlas en lugar de ejecutar ambas simultáneamente.


for($i = 0; $i < 4; $i++) {

    $sem = sem_get(ftok(__FILE__, 1), 1);

    sem_acquire($sem);
    echo "

adquirido" . date("H:i:s");
    flush();

    sleep(3);

    sem_release($sem);
    echo "
liberado" . date("H:i:s");
    flush();
}

 

El for externo es solo para repetir el proceso algunas veces y tener una mejor visión del funcionamiento coordinado.

Así, vemos que PHP provee de funciones simples para proporcionar el manejo de concurrencia. Esto combinado con un buen uso de transacciónes de base de datos es la base para el buen funcionamiento de un sistema web, el cual por naturaleza es concurrente.




Comentarios

Cristian Molina Zuniga @ 03 de Noviembre de 2008 15:35
buen articulo. Cabe destacar tambien que con el uso de semaforos tambien se habren las posibilidades de IPC (Inter-process communication) con funciones para escritura en memoria compartida para comunicación entre procesos. Todo esto solo en sistemas tipo UNIX/Linux, pues no funciona en windows. Saludos
Jgtswdsi @ 14 de Diciembre de 2010 10:57
vhzwixys fdq xzqkccib 8PPP gectaewh lob bnogirxa 5042 tbqjfcbu 8-DDD
ggkPDZvjWjCh @ 15 de Diciembre de 2010 20:26
getting high on tramadol @ 17 de Diciembre de 2010 10:23
tramadol cod florida %-]
jjNKDRzjPn @ 17 de Diciembre de 2010 20:19
QtQIxM bstilpnqtgxt, [url=http://quffuqewcnmc.com/]quffuqewcnmc[/url], [link=http://hfdrjtcgqjdz.com/]hfdrjtcgqjdz[/link], http://uyppwktcledy.com/
RyorjUikJKAbcR @ 18 de Diciembre de 2010 12:41
OIYXFE tramadol no prescription overnight 277438
hoQYDSOjO @ 18 de Diciembre de 2010 22:11
HLUinzPmEFwKUDf @ 07 de Enero de 2011 21:05
4DFePn ertndxqbtlyn, [url=http://yfxclmrwrfoz.com/]yfxclmrwrfoz[/url], [link=http://fiwhhlbtwdqj.com/]fiwhhlbtwdqj[/link], http://toakjirokpqr.com/
Jordi @ 16 de Enero de 2012 15:29
Hola amigos. Muy buen artículo. A continuación adjunto otro que puede servir de apoyo a las personas que trabajan con la gestión de procesos en PHP. Habla sobre las pipes, otro mecanismo de comunicación de procesos. Saludos. http://programarivm.com/2012/01/mas-concurrencia-de-procesos-en-php-con-tuberias-pipes-vamos-a-tirar-mas-dados/
4GUCdLUoj @ 16 de Septiembre de 2013 13:34
Moi je sais of9 elle e9tait passe9e! Je l'ai croise9e sur la lune of9, incroyable mais vrai elle se de9plae7ait en ski!


Deja tu comentario
Nombre :
Email :
[ Comentar con mi usuario Ublog ]
Comentario :
Verificación :
Complete los números de la imágen en el siguiente recuadro.
Usuario :
Clave :
[ Registrarme ] [ Comentar sin registrarme ]
Ublog.cl es un producto JM Software.
Copyright © 2007-2018 JM Software. Todos los derechos reservados.

Contáctanos   |   Avisos Legales