Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    [PILLOLA] Sviluppare demoni per sistemi posix (Linux/*BSD/Mac OS X e cosi via)

    Hola a todos,

    dato che stamattina ho pubblicato i sorgenti della mia classe per lo sviluppo di demoni posix e ho creato anche la pagina sul GRUSP ne approfitto per scrivere una veloce pillolina che può sempre servire a qualcuno

    Premetto che la classe non fa altro che "facilitare" lo sviluppo di questo tipo di applicativi, ad esempio wrappa la funzione pcntl_fork e implementa oltre ai canonici controlli anche il supporto per sfruttare le funzioni wait e waitpid per verificare se il processo figlio termina normalmente o ha problemi. O ancora implementa un wrapper alle funzioni per settare utente/gruppo che permettono oltre a settare l'utente tramite ID (UID/GID) anche tramite nome

    Il codice è compatibile ESCLUSIVAMENTE con PHP5, anche se è facile il back port a PHP4 sinceramente lo sconsiglio dato che questo non è più supportato.

    Il vantaggio di questo tipo di applicativi è che è possibile integrarli con tanta roba (FAM [ www.php.net/FAM ] per la verifica delle operazioni sui dischi, integrazione per controlli su mysql, checking sui servizi di rete, interazione con le pagine web per l'esecuzione di operazioni e cosi via ... li dipende dalla vostra fantasia )

    Le funzionalità implementate sono le seguenti:[list=1][*]permette di eseguire il forking del processo senza terminare il processo padre e permette di metterlo in attesa automatica per verificare se il processo figlio ha problemi durante l'esecuzione per restituire automaticamente i codici di errori relativi al blocco[*]supporta la creazione di nuove sessioni, in modo da sganciarsi dalla console o dal sistema di inizializzazione[*]grazie all'OOP è semplicissimo scrivere demoni avanzati come quello presente nel secondo esempio (OwnPosixDaemonWithParent)[*]supporta lo switching dell'utente[*]supporta i segnali posix, gli allarmi ed il ripristino dei segnali[/list=1]

    Dovete scaricare il codice sorgente della classe dal mio sito, all'indirizzo
    http://www.phpsoft.it/node/37

    Una volta fatta l'operazione, all'interno della file ci sta oltre alla mia classe anche altre 2 classi che sono due esempi:
    - OwnPosixDaemon è un esempio abbastanza base che una volta effettuato il forking del processo e creata la nuova sessione nel sistema setta la gestione di alcuni segnali e avvia il loop principale dove svolge le proprie operazioni o si mette in attesa
    - OwnPosixDaemonWithParent è invece un pò più avanzato infatti prevede l'utilizzo di due processi ovvero uno controllore e un esecutore che derivano dal processo padre facendo 2 fork (il primo si sgancia dalla console facendo morire il parent mentre il child rilancia un fork lasciando due processi in esecuzione) ... il processo controllore tiene una fifo in lettura dalla quale legge i testi inviati dal processo esecutore che ogni volta che riceve un segnale USR1 manda una stringa e li visualizza a video

    Qui ci sono due esempi, di seguito quello procedurale:
    Codice PHP:
    <?php

    require_once('PosixDaemon.class.php');

    $posixDaemon = new PosixDaemon();
    $posixDaemon->Fork();
    $posixDaemon->DetachSession();

    $counter 0;
    while(
    $counter 5)
    {
        
    sleep(1);
        
    $counter++;
    }

    exit(
    PosixDaemon::EXIT_OK);

    ?>
    L'esempio invece che sfrutta l'OOP invece è qui:
    Codice PHP:
    <?php

    require_once('PosixDaemon.class.php');

    class 
    MyPosixDaemon extendes PosixDaemon
    {
        public function 
    __construct()
        {
            
    $this->Fork();
            
    $this->DetachSession();
            
    $this->MainLoop();
        }
        
        private function 
    MainLoop()
        {
            
    $counter 0;
            while(
    $counter 5)
            {
                
    sleep(1);
                
    $counter++;
            }

            exit(
    MyPosixDaemon::EXIT_OK);
        }
    }

    $myPosixDaemon = new MyPosixDaemon();

    ?>
    Com'è possibile capire, dato la semplicità, il metodo Fork si occupa di "sdoppiare" il processo clonando tutte le risorse mentre il metodo DetachSession si sgancia dalla sessione di sistema dalla quale viene lanciato e ne crea una nuova divenendone il gestore

    Fatta l'operazione avvia il loop del demone che, una volta raggiungo il valore di 4 per il counter, esce senza terminare con errori o altro!

    Di seguito c'è la descrizione dei vari metodi:
    - Fork accetta in ingresso due valori; il primo indica al metodo fork di non terminare il processo padre e farlo quindi gestire al codice chiamate che riceve in uscita due valori PosixDaemon::FORK_ISCHILD e PosixDaemon::FORK_ISPARENT ... i due valori vengono restituiti rispettivamente se in esecuzione è il processo figlio o il processo parent; il secondo parametro indica al metodo di gestire internamente l'attesa del processo figlio per verificare se termina correttamente o se invece termina per qualche motivo particolare ovvero se qualche segnale non gestito crea problemi o se viene abortito ... alternativamente il processo padre muore restituendo il codice di uscita del processo figlio che onde evitare di avere problemi con i valori restituiti dal codice base dovrebbe essere sempre superiore almeno a 20

    - DetachSession non accetta parametri in ingresso e si occupa di sganciarsi dalla sessione corrente e crea la nuova sulla quale sposta il processo

    - SetUserAndGroup accetta in ingresso due parametri, di cui il secondo opzionale, e sono il nome utente o l'uid ed il nome del gruppo o il gid

    - SetSignalHandler setta il gestore dei segnali posix/ansi/unix e accetta in ingresso come primo parametro il codice del segnale come singolo valore o come array di valori e come secondo parametro accetta la callback a cui passare le chiamate; la callback deve accettare un valore in entrata che corrisponde al codice del segnale ricevuto ... una sola callback può infatti gestire più segnali!

    - RestoreSignalHandler ripristina i segnali passati, sempre come singolo valore o come array di valori, settando il gestore dei segnali di default

    - SetAlarm accetta in ingresso il numero di secondi tra un segnale dall'allarme ed un altro e come secondo valore prende in ingresso la callback del segnale SIGALRM ... callback che è opzionale e se non passata va settata manualmente con il SetSignalHandler

    - MainLoop è solo un metodo fittizzio che può essere usato come riferimento per effettuare il ciclo principale del demone

    Che dire ... ho finito

    PS: se avete problemi con il ripristino dei segnali o con il gestore dei segnali potrebbe essere errato il SIG_IDF nel restore ... non ho avuto modo di testarlo abbondantemente perché sinceramente ho scritto il metodo giusto per averlo ma non l'ho mai usato! Inoltre il metodo che setta utenti e gruppi utilizza is_numeric per verificare se l'uid/gid sono numerici però potrebberò esserci dei nomi utenti o nomi di gruppi numerici ed in quel caso verrebberò trattati come UID e come GID quindi il codice li andrebbe sistemato (so già come sistemarlo ... ma non ho il tempo )

  2. #2
    Ciao,
    trovo molto interessante l'argomento però ancora non mi riesco a fare un'idea di "processi php".

    O meglio non mi vengono in mente situazioni d'uso...potresti chiarirmi un po questo aspetto?

    Quando ho un processo attivo su un sistema operativo (es. Unix/Linux), in questo caso un demone, lo posso usare per applicativi client/server (multi-client/server) o per ottenere dei servizi e fin qui ci siamo.

    Quando uso PHP come funziona la cosa? Quando può essermi utile gestire demoni o cmq il multi-processo (multi-threading) con php?

    Ripeto la cosa mi interessa molto perchè l'argomento mi affascina, sopratutto per le potenzialità del multi-threading, però in varie situazioni non ne colgo l'applicazione pratica!
    Administrator of NAMDesign.Net

  3. #3

  4. #4
    Originariamente inviato da LeaderGL
    Ciao,
    trovo molto interessante l'argomento però ancora non mi riesco a fare un'idea di "processi php"
    sono normalissimi processi di sistema, semplicemente quando viene "clonato" il processo viene clonato in tutto e per tutto l'interprete PHP con la relativa memoria e tutto quanto insomma e poi l'esecuzione continua normale sui due processi

    O meglio non mi vengono in mente situazioni d'uso...potresti chiarirmi un po questo aspetto?
    ovviamente se si guarda SOLO il lato web, il fork neanche si può fare perché esploderebbe mezzo webserver, però se si guarda il lato console e/o applicativi allora li ti assicuro che ci sono un miliardo di motivi per usarli

    ESEMPIO PRATICO!

    Youtube

    tu pensi che youtube, appena uploadi il video, la stessa pagina web faccia la conversione? ci sta un apposito servizio in esecuzione, o richiamato via cron ma facciamo finta che ci sta un servizio in esecuzione,.
    Una volta che PHP ha completato l'upload il servizio che sta in esecuzione scritto in php utilizza FAM (File Alternate Monitor - http://it2.php.net/fam ) che notifica a php che il file .avi è stato scritto in una data cartella ... il servizio a questo punto inizializza le informazioni per l'operazione e crea un fork in modo che il processo figlio sappia già cosa deve fare e dove farlo! Fatto questo si mette in comunicazione con il processo padre tramite una fifo o una socket unix e gli dice "papà sono partito e sto iniziando a convertire il file" ... oppure "guarda che sono arrivato al 30%" o ancora "sono arrivato al 70% ma ho riscontrato errore XXX"

    Il processo figlio, una volta che parte, va ad utilizzare ffmpeg per effettuare la conversione del video e, dato che l'operazione è bloccante, deve per forza farla un altro processo!

    Utilizzando le funzioni popen et simili la gestione del processo si fa con estrema tranquillità

    Quando ho un processo attivo su un sistema operativo (es. Unix/Linux), in questo caso un demone, lo posso usare per applicativi client/server (multi-client/server) o per ottenere dei servizi e fin qui ci siamo.
    non solo, l'esempio di su non rientra in questi casi

    Quando uso PHP come funziona la cosa? Quando può essermi utile gestire demoni o cmq il multi-processo (multi-threading) con php?

    Ripeto la cosa mi interessa molto perchè l'argomento mi affascina, sopratutto per le potenzialità del multi-threading, però in varie situazioni non ne colgo l'applicazione pratica!
    no, attenzione, c'è una NOTEVOLE differenza tra il forking, quindi processi separati che non hanno ASSOLUTAMENTE nulla a che fare tra loro se non il fatto che appartengono alla stessa sessione di processi (o stesso gruppo di processi ... cosa che comporta che se si chiude il parent i figli cascano giù)

    Il multi-threading php non lo supporta, o meglio, lui è perfettamente thread safe ma ci sono una serie di estensioni che non lo sono e che causano seri problemi poi a tutto il sistema! PHP infatti sotto IIS gira come FastCGI o come CGI nonostante ci stia il modulo PHP ISAPI con il multi thread abilitato che è MOLTO più performante

  5. #5
    Uhm, l'esempio di YouTube mi ha aperto la mente...ti ringrazio.

    Però adesso mi hai incuriosito ancora di più, sai dove posso documentarmi sull'uso di PHP in questi termini?

    Oppure se magari hai altri campi di applicazione noti mi farebbe piacere, ripeto l'argomento è molto interessante; e capirlo meglio aiuta ad apprezzare maggiormente la pillola che hai scritto
    Administrator of NAMDesign.Net

  6. #6
    Originariamente inviato da LeaderGL
    Uhm, l'esempio di YouTube mi ha aperto la mente...ti ringrazio.

    Però adesso mi hai incuriosito ancora di più, sai dove posso documentarmi sull'uso di PHP in questi termini?

    Oppure se magari hai altri campi di applicazione noti mi farebbe piacere, ripeto l'argomento è molto interessante; e capirlo meglio aiuta ad apprezzare maggiormente la pillola che hai scritto
    beh tutto dipende dalla propria fantasia

    ad esempio puoi scrivere sistemi che ti permettono di svolgere operazioni lunghe senza bloccare l'utente!

    Dalla pagina amministrativa lanci l'operazione (ad esempio una newsletter) e il demone la mette in coda alle operazioni da fare e ti da le statistiche ed i tempi di invio

    O ancora puoi sviluppare veri e propri servizi di rete (webserver, server di posta, server ftp, propri server di rete e cosi via)

  7. #7


    perchè quando daniele_dll dice qualcosa di tanto complesso sembra la cosa più semplice del mondo???

    cmq è affascinante la classe....complimenti
    Perchè essere stupidi non è una menomazione ma un diritto di tutti!!!

  8. #8
    Originariamente inviato da daniele_dll
    beh tutto dipende dalla propria fantasia

    ad esempio puoi scrivere sistemi che ti permettono di svolgere operazioni lunghe senza bloccare l'utente!

    Dalla pagina amministrativa lanci l'operazione (ad esempio una newsletter) e il demone la mette in coda alle operazioni da fare e ti da le statistiche ed i tempi di invio

    O ancora puoi sviluppare veri e propri servizi di rete (webserver, server di posta, server ftp, propri server di rete e cosi via)
    può offrirmi le statistiche ed i tempi di invio mentre io faccio altro? devo comunque prevedere una pagina (che l'utente naviga) che va ad interrogare qualcosa o altro?

    P.S. sai se sull'argomento ci sono libri interessanti?
    Administrator of NAMDesign.Net

  9. #9
    Originariamente inviato da LeaderGL
    può offrirmi le statistiche ed i tempi di invio mentre io faccio altro? devo comunque prevedere una pagina (che l'utente naviga) che va ad interrogare qualcosa o altro?

    P.S. sai se sull'argomento ci sono libri interessanti?
    si certo, una pagina web che faccia da ponte deve per forza esserci, ma non deve fare altro che connettersi tramite una socket unix o una pipe (o una fifo come nel secondo esempio) e inviare una richiesta che dall'altra parte viene letta, analizzata, e viene inviata una risposta

    se ad esempio invii (dove vedi {CHR[xxx]} è il carattere ascii corrispondente)

    TIPO-OPERAZIONE{CHR[254]}PARAMETRO-1{CHR[254]}PARAMETRO-2{CHR[254]}PARAMETRO-3{CHR[254]}....{CHR[254]}PARAMETRO-N{CHR[255]}

    il codice di analisi non deve fare altro che prendere il flusso di dati letto a blocchi di 8kb (il massimo che php legge) accodarlo al buffer già letto e poi mandare il tutto ad una funzione di analisi che tramite strpos cerchi il carattere ascii 255 fin quando non ne trova più. Una volta che non ne trova più effettua un sub string sul buffer passato per rimuovere la parte analizzata. La parte analizzata viene invece esplosa con explode e poi le singole linee vengono riesplode con explode.
    Dal primo array tu ottieni l'elenco dei comandi dal secondo invece ottieni l'elenco specifico delle sesioni del comando, ovvero il tipo di operazioni e l'elenco dei parametri

    In questo modo se richiami il metodo passando il buffer e un array vuoto inizializzato per riferimento dove scrivere l'elenco dei comandi acquisiti con le altre informazioni e reimposti il buffer con il valore restituito dal metodo (gli fai restituire la parte non analizzata o una stringa vuota se hai analizzato tutto)

    L'array che hai ricevuto conterrà SEMPRE nel primo rigo il tipo di operazione, che potrebbe essere un valore numerico o una stringa, mentre gli altri, se ci sono, sono veri e propri parametri.

    A questo punto, nel costruttore, crei un array dove fai l'accoppiata TIPO-OPERAZIONE => CALLBACK DI GESTIONE in modo che quando ti arriva quell'operazione prendi i parametri e cosi come sono li passi alla callback registrata nell'array (la callback la puoi impostare sull'oggetto corrente ad esempio facendo array(&$this, 'NomeCallback') come ho fatto con gli event handler dei segnali)

    La callback svolge le proprie operazioni e poi continua normalmente il tutto

    Nel caso che usi una FIFO/PIPE è meglio che, oltre al tipo di operazioni, ti fai inviare dal processo figlio un identificatore, volendo anche il process id stesso, in modo che sai esattamente chi è dato che non essendo una socket non ne hai possibilità (stesso discorso nel caso di una socket unix )

    Riguardo a php c'è pochissima documentazione, però se ti metti di pazienza puoi trovare sul GAPIL un sacco di roba (anche se gli esempi sono in C/C++ però comprensibili):
    - http://www.lilik.it/~mirko/gapil/gapilsu34.html
    - http://www.lilik.it/~mirko/gapil/gapilsu35.html
    - http://www.lilik.it/~mirko/gapil/gapilsu37.html
    - http://www.lilik.it/~mirko/gapil/gapilsu40.html
    - http://www.lilik.it/~mirko/gapil/gapilse9.html
    - http://www.lilik.it/~mirko/gapil/gapilse10.html

  10. #10

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.