Visualizzazione dei risultati da 1 a 3 su 3
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2003
    Messaggi
    30

    [PHP] Accesso esclusivo ai file

    Ciao, non ho ben capito come si fa a fare in modo che uno script PHP acceda
    ad un file in modo esclusivo, evitando che un'altro script vi acceda allo stesso tempo.

    Ho 2 pagine PHP pagina1 e pagina2 che accedono ad uno stesso file F, rispettivamente in lettura e scrittura.

    Se pagina1 legge F mentre pagina2 sta tentando di accedervi in scrittura, vorrei che pagina2 aspetti prima che la lettura sia finita, e viceversa.


    Ho guardato sui manuali come si usa la funzione flock, ma secondo me non funge perchè supponiamo che i due script siano fatti così :

    codice:
    PAGINA1  (lettura di F)
    
    $f = fopen(nomefile,"r");
    flock($f,LOCK_SH);
     // leggi il file F
    flock($f,LOCK_UN);
    fclose($f);
    
    PAGINA2  (aggiornamento di F)
    
    $f = fopen(nomefile,"w");
    flock($f,LOCK_EX);
     // scrivi sul file F
    flock($f,LOCK_UN);
    fclose($f);
    Se ci sono due thread diversi che eseguono pagina1 e pagina2 rispettivamente,
    potrebbe succedere questo:

    codice:
    1) Il thread2 esegue $f = fopen(nomefile,"w");
        e quindi tronca il file F che diventa un file vuoto
    
    2) Il thread2 viene sospeso e il thread1 viene ripreso
    
    3) Il thread1 apre il file F in lettura, chiama flock, 
        ed esegue  la lettura da F, quindi legge un file vuoto!! 
    
    4) Il thread1 sblocca il file con flock($f,LOCK_UN);
    
    5) Il thread1 viene sospeso e il thread2 riprende l'esecuzione,
        locka il file, ed esegue la scrittura.. ecc.

    Io ho un server Apache 2.x sotto Windows e non so sinceramente se sia multithread, ma suppongo di si , e poi comunque ormai siamo nell'era del multicore e credo che tutte le nuove applicazioni abbiano più di un thread, figuriamoci un server http...


    Quindi come si può evitare il problema?
    ciao

  2. #2
    Utente di HTML.it L'avatar di gianiaz
    Registrato dal
    May 2001
    Messaggi
    8,027

    Re: [PHP] Accesso esclusivo ai file

    Originariamente inviato da Belva
    Ciao, non ho ben capito come si fa a fare in modo che uno script PHP acceda
    ad un file in modo esclusivo, evitando che un'altro script vi acceda allo stesso tempo.

    Ho 2 pagine PHP pagina1 e pagina2 che accedono ad uno stesso file F, rispettivamente in lettura e scrittura.

    Se pagina1 legge F mentre pagina2 sta tentando di accedervi in scrittura, vorrei che pagina2 aspetti prima che la lettura sia finita, e viceversa.


    Ho guardato sui manuali come si usa la funzione flock, ma secondo me non funge perchè supponiamo che i due script siano fatti così :

    codice:
    PAGINA1  (lettura di F)
    
    $f = fopen(nomefile,"r");
    flock($f,LOCK_SH);
     // leggi il file F
    flock($f,LOCK_UN);
    fclose($f);
    
    PAGINA2  (aggiornamento di F)
    
    $f = fopen(nomefile,"w");
    flock($f,LOCK_EX);
     // scrivi sul file F
    flock($f,LOCK_UN);
    fclose($f);
    Se ci sono due thread diversi che eseguono pagina1 e pagina2 rispettivamente,
    potrebbe succedere questo:

    codice:
    1) Il thread2 esegue $f = fopen(nomefile,"w");
        e quindi tronca il file F che diventa un file vuoto
    
    2) Il thread2 viene sospeso e il thread1 viene ripreso
    
    3) Il thread1 apre il file F in lettura, chiama flock, 
        ed esegue  la lettura da F, quindi legge un file vuoto!! 
    
    4) Il thread1 sblocca il file con flock($f,LOCK_UN);
    
    5) Il thread1 viene sospeso e il thread2 riprende l'esecuzione,
        locka il file, ed esegue la scrittura.. ecc.

    Io ho un server Apache 2.x sotto Windows e non so sinceramente se sia multithread, ma suppongo di si , e poi comunque ormai siamo nell'era del multicore e credo che tutte le nuove applicazioni abbiano più di un thread, figuriamoci un server http...


    Quindi come si può evitare il problema?
    ciao
    flock() will not work on NFS and many other networked file systems. Check your operating system documentation for more details.

    On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!

    flock() is not supported on antiquated filesystems like FAT and its derivates and will therefore always return FALSE under this environments (this is especially true for Windows 98 users).
    Cosi a occhio è un metodo con molte limitazioni.

    Io seguirei l'esempio dei sistemi linux, che quando vogliono che un tipo di operazione sia lockata creano un file di lock appunto.

    In pratica prima di fare ogni operazione su un file crei un file (anche vuoto) che si chiami nomefile.lock.

    Ogni volta che vuoi operare sul file verifichi se esiste e in tal caso ti blocchi.

    Quando hai finito di operare sul file cancelli il file di lock rilasciando la possibilità ad altri file di accedervi.

    Gli effetti negativi sono:

    1. Devi usare lo stesso metodo in tutti gli script, altrimenti non funziona.
    2. Non hai la possibilità di gestire una coda di operazioni, semplicemente se il file non è accessibile lo script termina.

    Come appendice al punto 2, potrei suggerirti di mettere tutto in un :

    codice:
    if(file_exists('nomefile.lock')) {
    
      while(file_exists('nomefile.lock')) {
        // non faccio nulla
    
      }
      
    }
    
    // eseguo le operazioni che voglio
    ma il rischio è che se gli accessi al file sono molti, o se per qualche motivo uno script non riesca per qualche motivo a cancellare il file di lock ti ritroveresti uno script che va in timeout.

    ciao

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2003
    Messaggi
    30
    grazie per la tua attenzione, quindi tu dici che se il file di lock non esiste lo creo, eseguo le mie operazioni e poi lo cancello.
    se invece esiste aspetto che venga cancellato.

    quindi così :
    codice:
    while(file_exists("nomefile.lock")); // non faccio nulla fino a quando verrà cancellato
    
     $lockfile = fopen("nomefile.lock","w");
     fclose($lockfile);
    
      // eseguo le mie operazioni 
    
      // cancello il file di lock
     unlink("nomefile.lock");

    secondo me non funge, potrebbe succedere questo :

    codice:
    1) inizialmente il file di lock non esiste
    2) nel THREAD1 il ciclo while(file_exists("nomefile.lock"));  viene superato,
       e immediatamente dopo il thread viene sospeso
    3) il THREAD2 prende il controllo, supera il ciclo while(file_exists("nomefile.lock")); 
        esegue 
        $lockfile = fopen("nomefile.lock","w");
        fclose($lockfile);
    4) il thread2 viene sospeso e il thread1 riprende l'esecuzione, crea di nuovo il file
        di lock sovrascrivendolo e i due thread accedono allo stesso file in modo non
        esclusivo...

    Secondo me invece potrebbe funzionare questo :

    codice:
    $f = fopen($nomefile,$lettura_o_scrittura);
    
    while( !flock($f,LOCK_EX) );  // non faccio nulla finchè il lock non riesce
    
     // eseguo le mie operazioni
    
      // rilascio il file
    flock($f,LOCK_UN);
    $fclose($f);

    è corretto?

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 © 2025 vBulletin Solutions, Inc. All rights reserved.