Fa uns dies que a la feina vaig començar un petit projecte sobre la gestió de control d’accessos i control horari, això ens va suposar fer un estudi del que s’havia de fer abans de començar (com sempre). El tema és que amb tot això va sorgir que s’havia de implementar un petit servidor de tasques el qual gestionaría les tasques que s’envien cap als terminals d’access i control horari.
Com que el software proporcionat pel fabricant dels terminals només és de comunicacions amb les terminals, hem hagut de implementar tot el tema de la API que comunica l’aplicacio de RRHH amb el servidor de terminals, després com es realitzarien els canvis que es fan a l’aplicació de RRHH damunt els terminals (crear empleats, modificar incidències i descarregar marcatges, …). Tot ens duia allà mateix: sería necessàri gestionar aquestes tasques! Però això no va esser el que ens va dur a utitlitzar fork’s amb PHP si no que a més aquest servidor es comunicaria amb els clients de lectura d’empremtes digitals per donar d’alta als empleats.
A partir d’aqui em vaig posar en marxa amb el tema. El servidor tendria dues tasques: una dedicada a la gestió de tasques generals destinades als terminals, i l’altre dedicada a escoltar per un socket TCP i que es comunicaría amb el client que te el lector d’empremtes. Tot això implicaría l’ús del fork i altres funcions emprades en multiprogramació (kill, signal, …). I tot això és pot fer amb PHP? pues sí …
Com que el PHP es pot emprar de la mateixa manera que el Perl, Python, … també el podem invocar desde un terminal, només hem de crear un fitxer amb la capçalera típica: #!/usr/bin/php que diu al loader del sistema operatiu amb quin executable ha de arrancar lo que vingui després de la capçalera i fer que el fitxer sigui executable.
Petit exemple d’introducció:
#!/usr/bin/php
<?php
function acabar_fill($signo)
{
echo "Process fill acabat!";
exit(0);
}
function fill()
{
pcntl_signal(SIGTERM, "acabar_fill");
while(1)
{
// Proces del fill
usleep(1000); // Evitar espera activa, envia el proces a dormir
}
}
// Codi principal del proces pare
if (($pid = pcntl_fork()) == 0)
{
fill();
exit(0);
}
else if ($pid!=-1)
pcntl_waitpid($pid, $status);
echo "El pare ha acabat!\n";
?>
Aqui tenim un petit exemple aqui on s’empren les funcions signal, wait i fork de php, on podem observar que el fill simplement te un bucle infinit amb un usleep (molt important!) sempre que tinguem bucles dins procesos, a més d’aquest estil. Si no hagués funcio usleep el process fill consumiría tots els cicles de CPU quedant amb espera activa, i això sempre ho hem d’evitar! Aquest petit exemple simplement ens crea un fill el qual ara mateix no fa res fins que l’hi enviam la senyal SIGTERM que controlam amb el pcntl_signal i que simplement fa aturar el process i es mor.
tomeu 21255 0.9 0.3 26792 8152 pts/0 S 17:16 0:00 /usr/bin/php ./agent.php tomeu 21256 0.0 0.1 26792 3224 pts/0 S 17:16 0:00 /usr/bin/php ./agent.php
Quan executem el nostre programa de prova desde la consola podrem veure amb el ps el pare i el fill i el consums respectius de CPU i memòria. Per aturar-lo simplement podem fer: kill -TERM <pid_fill>.
A part d’aquestes funcions hi ha totes les que permeten la comunicació entre processos (IPC) com els missatges, memòria compartida i semàfors.