PDA

View Full Version : [C] Scrittura concorrente in file


Unrue
02-01-2007, 11:33
Salve,
mi domandavo come fare per far scrivere contemporaneamente a più processi nello stesso file binario. Ho provato a dire ad ogni processo di scrivere nel file posizionando il puntatore con fseek, solo che ogni volta ovviamente il file viene sovrascritto dall'ultimo processo che arriva. Grazie.

andbin
02-01-2007, 12:16
mi domandavo come fare per far scrivere contemporaneamente a più processi nello stesso file binario. Ho provato a dire ad ogni processo di scrivere nel file posizionando il puntatore con fseek, solo che ogni volta ovviamente il file viene sovrascritto dall'ultimo processo che arriva. Grazie.Far scrivere a più processi sullo stesso file ma in punti diversi non credo che sia un problema (dovrei comunque verificare bene).
Mentre invece il problema esiste sicuramente per scritture contemporanee nello stesso punto.
In ogni caso sarebbe meglio fare un lock del file (o di una parte del file, se è possibile), fare le modifiche, e poi togliere il lock.
Comunque quando passa di qui qualcuno più esperto sull'argomento, saprà dirti sicuramente meglio. ;)

Johnn
02-01-2007, 15:24
Non consideratemi esperto, ma non si avrebbero problemi anche nella scrittura contemporanei in punti diversi per il fatto che non sarebbe più coerente la posizione?

Io avrei detto di usare i semafori, o comunque un qualsiasi strumento di mutua esclusione.

Unrue
02-01-2007, 15:30
Non consideratemi esperto, ma non si avrebbero problemi anche nella scrittura contemporanei in punti diversi per il fatto che non sarebbe più coerente la posizione?

Io avrei detto di usare i semafori, o comunque un qualsiasi strumento di mutua esclusione.

In che senso non sarebbe più coerente la posizione?

Unrue
02-01-2007, 15:31
Far scrivere a più processi sullo stesso file ma in punti diversi non credo che sia un problema (dovrei comunque verificare bene).
Mentre invece il problema esiste sicuramente per scritture contemporanee nello stesso punto.
In ogni caso sarebbe meglio fare un lock del file (o di una parte del file, se è possibile), fare le modifiche, e poi togliere il lock.
Comunque quando passa di qui qualcuno più esperto sull'argomento, saprà dirti sicuramente meglio. ;)

In realtà a me va bene anche che scriva uno per volta, ovviamente in punti diversi.

andbin
02-01-2007, 15:38
Non consideratemi esperto, ma non si avrebbero problemi anche nella scrittura contemporanei in punti diversi per il fatto che non sarebbe più coerente la posizione?La posizione all'interno del file è legata al "handle" (o descrittore, come vuoi chiamarlo) aperto dal processo. Non è una cosa "globale"

Io avrei detto di usare i semafori, o comunque un qualsiasi strumento di mutua esclusione.No ... come farebbero le applicazioni A (sviluppata da Tizio) e B (sviluppata da Caio) a sapere che per accedere, in modo esclusivo, ad uno stesso file, si devono usare dei semafori, mutex o altro???

recoil
02-01-2007, 15:49
esattamente come devono avvenire le scritture? devi posizionarti in un punto preciso o basta che tu scriva alla fine del file ogni volta?

71104
02-01-2007, 15:54
in Win32 esiste l'overlapped I/O, che supporta già da solo tutta la sincronizzazione necessaria a risolvere il problema.

EDIT - no scusate, non vorrei aver detto una boiata, controllo meglio... :mbe:
EDIT2 - boh, non è che sia esplicitato molto bene, ma mi pare di aver capito che se una lettura overlapped avviene contemporaneamente a una scrittura overlapped, i dati letti non sono "inconsistenti"; mentre se le due non operazioni fossero overlapped i dati letti potrebbero essere inconsistenti.

andbin
02-01-2007, 15:58
in Win32 esiste l'overlapped I/O, che supporta già da solo tutta la sincronizzazione necessaria a risolvere il problema.L'overlapped I/O è solo .... un I/O asincrono (le funzioni ritornano subito e il risultato ... successivamente). Non ha nulla a che fare con la concorrenza nella scrittura o con il locking.

71104
02-01-2007, 16:09
L'overlapped I/O è solo .... un I/O asincrono (le funzioni ritornano subito e il risultato ... successivamente). Non ha nulla a che fare con la concorrenza nella scrittura o con il locking. credo che la sincronizzazione per evitare l'inconsistenza delle operazioni di I/O sia una conseguenza dell'implementazione dell'overlapped I/O, ma in effetti è meglio non farci affidamento. per definizione l'unica garanzia che ti da' l'overlapped I/O è il poter ricevere in un secondo momento la notifica di terminazione di operazioni lunghe.

Unrue
02-01-2007, 16:50
esattamente come devono avvenire le scritture? devi posizionarti in un punto preciso o basta che tu scriva alla fine del file ogni volta?

No, in un punto preciso, devo scriverci una matrice.

Unrue
03-01-2007, 11:33
Ho scritto questo:

void scrivi_file(float**matrice_trasposta_locale,int lx,int dim_mat,int me)
{
struct flock fl;
int fd;
off_t offset;
int ris;
fl.l_type= F_WRLCK; /* tipo di lock*/
fl.l_whence = SEEK_SET; /* offset */
fl.l_start = 0; /* Offset per l_whence */
fl.l_len = 0; /* length, 0 = to EOF */
fl.l_pid = getpid(); /* our PID */


fd = open("home/gabriele/Desktop/output", O_WRONLY); //fd è il Descrittore del file


fcntl(fd, F_SETLKW, &fl); // Attendi per avere il lock
lseek(fd, dim_mat*lx*me*sizeof(float),fl.l_whence);
int i;
int j;


for(j=0;j<lx;j++)
{
for(i=0;i<dim_mat;i++)
{
printf(" Sono arrivato : %d \n",me);
ris=write(fd,&matrice_trasposta_locale[i][j],1);
printf("Valore : %2.1f da %d \n ",matrice_trasposta_locale[i][j],me);
printf("Risultato: %d \n",ris);
}
}

fl.l_type = F_UNLCK;
fcntl(fd, F_SETLK, &fl);



}

La cosa strana è che le scritture avvengono a video correttamente, ma nel file non scrive,infatti la write ritorna sempre -1

andbin
03-01-2007, 11:44
La cosa strana è che le scritture avvengono a video correttamente, ma il file non c'è!!Verifica bene la documentazione di open()!
fd = open("home/gabriele/Desktop/output", O_WRONLY | O_CREAT);Mettendo solo O_WRONLY, la open fallisce se il file non esiste già. Con O_CREAT, se non c'è, lo crea.

Unrue
03-01-2007, 11:52
Grazie del suggerimento,però open continua a ritornarmi -1 :( Sono sotto Linux, forse c'è un problema di permessi per scrivere nella cartella?

andbin
03-01-2007, 11:58
Grazie del suggerimento,però open continua a ritornarmi -1 :( Sono sotto Linux, forse c'è un problema di permessi per scrivere nella cartella?Beh, verifica bene il path! Visto così suppongo che debba essere:

/home/gabriele/Desktop/output

Unrue
03-01-2007, 12:06
Ma por... vero :p . Adesso il primo processo che arriva apre il file e ci scrive,però gli altri che vengono dopo ritornano -1 sempre alla open. L'attesa per prendere il lock la fa la fcntl con F_SETLKW, non capisco.. Sembra che gli altri non attendano di prendere il lock ed escano subito.

Unrue
03-01-2007, 12:14
Ho capito perchè: il primo processo crea il file. Ma tale file non ha permessi di scrittura. Ho provato a metterci un file vuoto ed a dare tutti i permessi in scrittura e lettura ed adesso tutti ci scrivono,strano però..

andbin
03-01-2007, 12:33
Stavo leggendo adesso la documentazione di fcntl(). F_GETLK, F_SETLK e F_SETLKW sono definiti "Advisory locking". Vuol dire che non gestiscono un reale blocco "forzato" sul file. Vanno bene solo quando i processi "cooperano" insieme, cioè sanno di dover lavorare su un file comune e quindi effettuano questo tipo di lock.

Per dirla in breve: apri un file di testo con la open(), fai il lock e poi prova, da un altro prompt, a fare echo "blabla" > file. Vedrai che la echo scrive sul file. Tu pensi: ma l'ho bloccato!! Sì ma echo non "coopera" e non usa fcntl per fare il lock.

In definitiva: usare F_GETLK, F_SETLK e F_SETLKW non ti para il sedere da qualunque altro processo che vuole scrivere sul file.

Johnn
03-01-2007, 12:48
La posizione all'interno del file è legata al "handle" (o descrittore, come vuoi chiamarlo) aperto dal processo. Non è una cosa "globale"

No ... come farebbero le applicazioni A (sviluppata da Tizio) e B (sviluppata da Caio) a sapere che per accedere, in modo esclusivo, ad uno stesso file, si devono usare dei semafori, mutex o altro???

Premetto che non ho tanto tempo, quindi post frettoloso.

La prima parte mi convince, parzialmente però quando ho tempo mi documenterò meglio, comunque ok.

La seconda, come anche è ripetuto nell'ultimo post, non l'ho capita: nel senso che motivo c'è di essere cautelati da scritture di processi non previsti? Non mi pare sia richiesto da Unrue. Se si volesse così, penso si debba pensare su due livelli: uno di mutua esclusione e un altro di controllo di accesso al file (permessi?).

beppegrillo
03-01-2007, 13:09
Premetto che non ho tanto tempo, quindi post frettoloso.

La prima parte mi convince, parzialmente però quando ho tempo mi documenterò meglio, comunque ok.


Su Os *unix, la cosa è gestita mediante due tabelle, una di tipo globale in cui vi sono fisicamente i dati e l'altra di tipo utente che recupera le informazioni da quella globale e ne possiede di proprie (ad. es offset)
Per questo motivo se esegui scritture con processi diversi, non apriranno due volte lo stesso file, ma ciascun vedrà il file come proprio.

Unrue
03-01-2007, 15:02
Stavo leggendo adesso la documentazione di fcntl(). F_GETLK, F_SETLK e F_SETLKW sono definiti "Advisory locking". Vuol dire che non gestiscono un reale blocco "forzato" sul file. Vanno bene solo quando i processi "cooperano" insieme, cioè sanno di dover lavorare su un file comune e quindi effettuano questo tipo di lock.

Per dirla in breve: apri un file di testo con la open(), fai il lock e poi prova, da un altro prompt, a fare echo "blabla" > file. Vedrai che la echo scrive sul file. Tu pensi: ma l'ho bloccato!! Sì ma echo non "coopera" e non usa fcntl per fare il lock.

In definitiva: usare F_GETLK, F_SETLK e F_SETLKW non ti para il sedere da qualunque altro processo che vuole scrivere sul file.

Ma i miei processi cooperano eccome! Ognuna è l'istanza di un processore nell'ambiente di programmazione parallela MPI.

Unrue
04-01-2007, 14:11
Adesso funziona perfettamente, l'unica cosa è che devo prima creare un file vuoto per poi farlo aprire dal primo processo che arriva, altrimenti il primo che arriva lo crea senza permessi di scrittura per gli altri processi e quindi non riescono a scriverci. Lo sapete come si fa a crearlo direttamente con tutti i permessi di scrittura?

andbin
04-01-2007, 14:29
Adesso funziona perfettamente, l'unica cosa è che devo prima creare un file vuoto per poi farlo aprire dal primo processo che arriva, altrimenti il primo che arriva lo crea senza permessi di scrittura per gli altri processi e quindi non riescono a scriverci. Lo sapete come si fa a crearlo direttamente con tutti i permessi di scrittura?A dire il vero, se si passa il flag O_CREAT, la open accetta un terzo parametro, preso come tipo 'mode_t'.

Quindi ad esempio:
fd = open ("....", O_CREAT | O_WRONLY, S_IRWXU | S_IRGRP | S_IROTH);

Unrue
04-01-2007, 15:46
Fantastico, grazie!

Unrue
10-01-2007, 20:26
A dire il vero, se si passa il flag O_CREAT, la open accetta un terzo parametro, preso come tipo 'mode_t'.

Quindi ad esempio:
fd = open ("....", O_CREAT | O_WRONLY, S_IRWXU | S_IRGRP | S_IROTH);


Allora, ho due domande. La prima è che il tuo codice non mi va in quanto mi dice che S_IRWXU non è definita. Neanche se definisco tutto prima con :

mode_t mode = S_IRWXU | S_IRGRP | S_IROTH

e poi inserisco mode nella open.

La seconda domanda è se è possibile fare delle maschere di lock. Nel senso, che io ho bisogno di scrivere nel file a tratti, ad esempio 4 bytes si e 4 bytes no. Però vorrei farlo se possibile lockando subito tutte le zone che mi interessano e non una per volta. Vorrei evitare anche di lockare tutto il file ogni volta. Grazie.