View Full Version : [C] Funzione access()
Mi servivano alcune delucidazioni riguarda la funzione access(). Per vedere se un file esiste gli passo il nome del file e la costante F_OK giusto? Il nome del file deve comprendere l'estensione? E alla fine se il file esiste che valore mi torna la funzione? Grazie.
ilsensine
23-03-2006, 12:55
Mi servivano alcune delucidazioni riguarda la funzione access(). Per vedere se un file esiste gli passo il nome del file e la costante F_OK giusto?
Sì. Anche se il metodo non è proprio corretto (il file potrebbe essere eliminato da qualcuno subito dopo la chiamata access)
Il nome del file deve comprendere l'estensione?
Sì
E alla fine se il file esiste che valore mi torna la funzione?
0
Ok grazie. E per vedere se un file è già aperto con access() si può?
ilsensine
23-03-2006, 13:30
mmm non credo.
No perché siccome devo controllare anche se un file è già aperto (e quando il file aperto ha estensione .$$$) mi chiedevo se si potesse fare. Quindi come potrei fare per controllare questa cosa?
Non potrei ad esempio verificare sempre con access() l'esistenza del file con estensione .$$$? Cioè io gli passo il file con l'estensione $$$ e se mi torna 0 allora so che è aperto.
ilsensine
23-03-2006, 14:35
Non sono esperto di win32, ma immagino che ci siano modi più efficaci per farlo.
Il programma verrà compilato sotto Linux. ;)
sottovento
23-03-2006, 16:44
Ma... intendi aperto da chiunque o dalla tua stessa applicazione?
ilsensine
23-03-2006, 16:55
Il programma verrà compilato sotto Linux. ;)
Allora devi fare come fa fuser...ovvero sfogliarti /proc/%d/fd/*...
In alternativa puoi usare inotify, ma credo che abbia effetto solo da quando crei il watch in poi
x sottovento:
Qui stiamo implementando solo una libreria. Sicuramente sarà aperto da chiunque.
x ilsensine:
purtroppo non posso usare path nel mio programma. Ma a rigor di logica con access() secondo la procedura che ti ho descritto prima non potrebbe andare teoricamente?
ilsensine
23-03-2006, 17:51
x ilsensine:
purtroppo non posso usare path nel mio programma.
Bè ok...ma /proc è un file system virtuale, non vedo perché non potresti usarlo...
Ma a rigor di logica con access() secondo la procedura che ti ho descritto prima non potrebbe andare teoricamente?
No, access non indica se un file è già aperto. E' questa una informazione abbastanza complicata da ottenere, per come funziona linux (vedi il casino che fa fuser...). Puoi ad esempio eliminare un file eseguibile mentre è...in esecuzione, senza che il programma in esecuzione si accorga di nulla!
inotify potrebbe aiutarti, ma dovresti implementare un demone che effettua il monitoraggio dei file che ti interessano (se sono noti a priori).
sottovento
23-03-2006, 17:55
x sottovento:
Qui stiamo implementando solo una libreria. Sicuramente sarà aperto da chiunque.
x ilsensine:
purtroppo non posso usare path nel mio programma. Ma a rigor di logica con access() secondo la procedura che ti ho descritto prima non potrebbe andare teoricamente?
Ciao,
all'interno dello stesso processo, puoi usare la stat(). Avendo il descrittore del file, la stat() ti da una serie di informazioni quali inode, ...
Le stesse info le puoi ottenere dato il nome del file. Quindi puoi sapere se il processo attuale ha gia' aperto il file in questione.
Per il controllo fra diversi processi... beh, e' veramente dura.
Per ora mi vengono in mente solo soluzioni parziali, e che ti obbligano a scrivere parecchio codice.
High Flying
Sottovento
ilsensine
23-03-2006, 18:00
all'interno dello stesso processo, puoi usare la stat(). Avendo il descrittore del file, la stat() ti da una serie di informazioni...
...non utili a stabilire se il file è già aperto. Anche per vedere se è già aperto dal processo corrente, devi spulciarti /proc/self/fd/*
Ok grazie.. vedo che sono soluzioni molto complicate :(
Nel nostro corso all'università non siamo ancora a questi livelli di programmazione. Possibile che i nostri prof ci abbiano dato una cosa così avanzata da fare? :cry:
La cosa più semplice quale sarebbe? :D
Cioè per farvela breve io devo implementare questa funzione:
int DeleteDatabaseFile ( char * Name )
Cancella un file di database con nome Name.
Name è una stringa non nulla e NULL terminated e rappresenta il nome del file da cancellare.
Il nome deve essere quello di un DBF precedentemente creato con la funzione CreateDatabaseFile() (che già ho provveduto a creare).
La lunghezza totale del nome viene troncata a DBF_NAME_LENGTH caratteri e viene aggiunta l'estensione DBF_EXTENSION.
Il database deve essere chiuso, cioe' non deve esistere un file con lo stesso nome e estensione DBF_OPEN_EXT.
Parameters:
[in] Name Nome del database file, stringa alfanumerica + '_' NULL terminated.
Returns:
LPC_OK Database cancellato
LPC_BAD_ARG Nome DB nullo o non valido
LPC_DBF_OPEN Il database è aperto.
LPC_FILE_ACCESS Il file non esiste o non può essere cancellato.
ilsensine
23-03-2006, 18:08
La cosa più semplice quale sarebbe? :D
Vuoi dire la cosa _giusta_ quale sarebbe? Sicuramente non la tua logica, perché è soggetta a race. Ad esempio se la tua libreria implementa qualcosa del tipo:
if (!isFileOpen(fname))
OpenFile(fname);
else
ErrorFileIsOpen();
hai una bella race tra il controllo e l'apertura del file. Queste situazioni si gestiscono con gli advisory lock oppure con i mandatory lock.
sottovento
23-03-2006, 18:10
...non utili a stabilire se il file è già aperto. Anche per vedere se è già aperto dal processo corrente, devi spulciarti /proc/self/fd/*
Puoi scandire la lista dei descrittori della tua file table (l'apposito #include ti da la sua lunghezza). Per ogni descrittore puoi ottenere se e' in uso. Nel caso sia in uso, la stat ti dice l'inode. La stessa info la ottieni dal nome del file. Pertanto e' possibile stabilire se il file e' aperto (dal processo attuale) semplicemente usando la stat
ilsensine
23-03-2006, 18:11
Il database deve essere chiuso, cioe' non deve esistere un file con lo stesso nome e estensione DBF_OPEN_EXT.
Ah quindi il vostro professore vuole che utilizziate i lockfile. Un lockfile è un file che contiene il pid del processo che ha aperto il db. Può essere creato in maniera atomica e senza race, creando prima un file temporaneo e poi tentando un link() (hard link) al nome del file vero e proprio. Devi gestire anche il caso in cui un precedente chiamante è "morto" senza eliminare il lockfile.
ilsensine
23-03-2006, 18:16
l'apposito #include ti da la sua lunghezza
L'apposito #include (immagino che stai parlando di FD_SETSIZE) ti fornisce la lunghezza _di default_ da usarsi per la (odiosa) select, che non ha nulla a che vedere con i file che il programma può aprire (e che puoi ridefinire a un valore diverso prima dell'include -- verrà usato il valore da te impostato, in questo caso). Il limite per processo sui file apribili è gestito da ulimit, e ha comunque un massimo assoluto nel kernel (e stiamo parlando di decine di migliaia di file descriptor, se non più, su un sistema normale). E' un metodo lento e poco pratico, e anche questo soggetto a race (v. ambienti multithread).
sottovento
23-03-2006, 18:31
L'apposito #include (immagino che stai parlando di FD_SETSIZE).
No
ti fornisce la lunghezza _di default_ da usarsi per la (odiosa) select, che non ha nulla a che vedere con i file che il programma può aprire (e che puoi ridefinire a un valore diverso prima dell'include -- verrà usato il valore da te impostato, in questo caso).
D'accordissimo
Il limite per processo sui file apribili è gestito da ulimit, e ha comunque un massimo assoluto nel kernel (e stiamo parlando di decine di migliaia di file descriptor, se non più, su un sistema normale).
Verissimo
E' un metodo lento e poco pratico, e anche questo soggetto a race (v. ambienti multithread).
No. Tutti i sistemi UNIX apriranno il primo descrittore disponibile. E' una specifica a cui tutti devono attenersi, ed e' utilizzata dalla shell stessa per le redirezioni.
Pertanto e' un sistema velocissimo: controllera' solo i file aperti. E non e' soggetto a race.
Esempio (un po' stupido). Assumendo che tutte le funzioni vadano a buon fine
f1 = open (...); // f1 = 3
f2 = open (...); // f1 = 4
close (f1);
f3 = dup (f2) ; // f3 = 3
Ad ogni modo, la soluzione che hai proposto prima, quando sono state date maggiori informazioni, e' quella giusta per la risoluzione del problema in questione. Questa discussione e' solo per chiarire alcuni aspetti che probabilmente interessano solo a noi due :)
High Flying
Sottovento
Non siamo ancora arrivati a gestire processi nel nostro corso (e non ci arriveremo fino al prossimo anno). In questo periodo inizieremo a vedere efficienza dei programmi e algoritmi su liste e alberi.
Sarei in grado ugualmente di fare una cosa simile? :)
sottovento
23-03-2006, 18:49
Non siamo ancora arrivati a gestire processi nel nostro corso (e non ci arriveremo fino al prossimo anno). In questo periodo inizieremo a vedere efficienza dei programmi e algoritmi su liste e alberi.
Sarei in grado ugualmente di fare una cosa simile? :)
La soluzione basata sui lockfile, come ti ha suggerito ilsensine, fa al caso tuo. Si tratta solo di aprire un file (e poche altre operazioni)
High Flying
Sottovento
Ok ci proverò e vi farò sapere. Grazie mille ;)
ilsensine
24-03-2006, 08:24
No
A quale ti riferifi allora? Il limite di file che possono essere aperti può variare da sistema a sistema, e da kernel a kernel...
No. Tutti i sistemi UNIX apriranno il primo descrittore disponibile. E' una specifica a cui tutti devono attenersi, ed e' utilizzata dalla shell stessa per le redirezioni.
Pertanto e' un sistema velocissimo: controllera' solo i file aperti. E non e' soggetto a race.
Esempio (un po' stupido). Assumendo che tutte le funzioni vadano a buon fine
f1 = open (...); // f1 = 3
f2 = open (...); // f1 = 4
close (f1);
f3 = dup (f2) ; // f3 = 3
La race la hai se un secondo thread esegue l'apertura di f3, mentre il primo thread sta sfogliando l'elenco degli fd e ha appena stabilito che l'fd 3 risulta chiuso.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.