2009-11-15 7 views
0

J'essaie de projeter un fichier en mémoire pour pouvoir l'utiliser. Le fichier contais structs donc j'essaye d'utiliser un pointeur au début d'une structure puis de le lire et de modifier une variable. Le problème est que le temps d'exécution est élevé et je suppose qu'en utilisant mmap le temps sera moindre. Ceci est le code, une suggestion?Projection de fichier en mémoire à l'aide de mmap

#include <unistd.h> 
#include <sys/stat.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 

int revisanotas(int fd) 
{ 
int nbytes=1; 
int nbytese=0; 
int i=0; 
int n=0; 
struct stat datos; 
fstat(fd, &datos); 
evaluacion buf; 
evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 
int actual = read(fd,buffer,datos.st_size); 
{ 
i++; 
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5) 
{ 
n=n+1; 
printf("Notamedia = %f\n",buffer[i].notamedia); 

buffer[i].notamedia=5; 
} 

}while (i<(datos.st_size/(sizeof(evaluacion)))); 
return 
+0

Vous manquez un 'do' après l'appel de' read'? –

Répondre

2

Eh bien, tout d'abord, s'il vous plaît nous dire ce que evaluacion est défini comme, et mis le do là-dedans qui correspond à la while; Je suppose que c'est juste après la ligne "int réelle". Deuxièmement, il semble que vous appeliez mmap() plus souvent que nécessaire; à quelle fréquence est revisanotas() appelé avec le même fd? L'appel mmap lui-même est lent, comme malloc; la vitesse est lorsque vous utilisez le fichier mappé, dans ce cas, les données pointées par buffer. Troisièmement, calculez datos.st_size/(sizeof(evaluacion)) une fois en dehors de la boucle et modifiez la clause while pour la comparer à celle-ci. Le code actuel semble effectuer la division une fois par itération à travers la boucle, et les divisions sont lentes.

Voir si cela aide tout.

2

L'appel à read() est inutile. Mmap()cartes le contenu du fichier en mémoire pour vous - c'est pourquoi il est généralement plus rapide que la lecture du fichier entier en utilisant read(). Vous devriez être en mesure de supprimer l'appel à read() tout à fait. Cependant, il y a d'autres problèmes avec votre code.

Si vous souhaitez que les modifications soient reflétées dans le fichier disque, vous devez appeler le msync(buffer, dataos.st_size, MS_SYNC). Lorsque vous avez terminé, appelez munmap(buffer, dataos.st_size) pour libérer le segment de mémoire partagée. Pensez à msync() comme la mémoire partagée équivalente à fflush() et munmap() est similaire à close(). La principale différence entre munmap() et close() est que le premier ne vide pas les tampons ou ne se synchronise pas sur le disque, donc vous devez le faire vous-même.

+0

Merci beaucoup, j'ai enlevé le read() et le temps diminue dramatiquement :).Maintenant, j'essaie de comprendre comment utiliser msync, car ce que je dois faire est de modifier la variable notamedia dans chaque structure qui correspond à la condition, puis d'écrire dans le disque le fichier entier modifié. – Peter

+0

Après avoir fini de modifier toutes les valeurs, appelez 'msync()' sur tout le segment de données. Si les modifications apportées à chaque structure doivent être visibles pendant la modification, appelez 'msync (& buffer [i], sizeof (tampon [i]), MS_SYNC)' après avoir effectué la modification. Je ne suis pas sûr si vous pouvez en toute sécurité en raison de ce dernier, bien que les éléments «tampon» individuels ne sont probablement pas alignés page. Mieux vaut faire le segment entier en même temps après que la boucle soit faite. –

+0

C'est faux. Il n'est pas nécessaire d'utiliser 'msync' pour que les modifications soient reflétées dans le fichier. –

0
Thanks mike for the answer, the struct is something like this and it's defined in a header file: 

struct evaluacion 
{ char id[16]; 
char apellido1[32]; 
char apellido2[32]; 
char name[32]; float nota1p; 
float nota2p; 
float notamedia; 
char photofilename[20]; 
int photosize; 
char photodata[16000]; 
}; 

Il n'y a qu'une seule fd, un seul fichier ouvert, mais beaucoup struct à l'intérieur

0

Je fais quelques progrès, je pense, mais il semble que je ne suis pas modifier le fichier. Si je lance le programme une fois, il détecte 32 variables modifiées, mais si je cours deux fois toujours le même, quand le Il est censé être modifié :(

Le temps d'exécution est maintenant pas mal je pense

int revisanotas(int fd) 
{ 
int i=0; 
int n=0; 
struct stat datos; 
fstat(fd, &datos); 
int num=datos.st_size/(sizeof(evaluacion)); 
evaluacion buf; 
evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 
do 
{ 
i++; 
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5) 
{ 
n=n+1; 

buffer[i].notamedia=5; 
} 
msync(&buffer[i],sizeof(buffer[i]),MS_SYNC); 
}while (i<(num)); 
munmap(buffer,datos.st_size); 
return(n); 
} 
+0

Vérifiez la valeur de retour de 'msync'. Ma conjecture est qu'il échoue, en retournant -1, et en mettant 'errno' à' EINVAL' (22). Essayez d'appeler 'msync (buffer, dataos.st_size, MS_SYNC)' avant d'appeler 'munmap'. –

+0

J'ai fait: int r = msync (tampon, datos, st_size, MS_SYNC); mmunmap (buffer, datos.st_size), Semble que msync renvoie 0 Correctme ​​si je me trompe, mais dois-je faire quelque chose pour écraser le fichier original décrit par le 'fd'? ou une fois que je libère la mémoire et écrire avec msync sera écrit dans le fichier? – Peter

0

Je pense maintenant travaille :), le code est le suivant. S'il vous plaît commenter si vous voyez quelque chose de mal:

int revisanotas(int fd) 
{ 
int i=0; 
int n=0; 
struct stat datos; 
fstat(fd, &datos); 
int num=datos.st_size/(sizeof(evaluacion)); 

evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
do 
{ 
i++; 
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5) 
{ 
n=n+1; 
buffer[i].notamedia=5; 
} 

}while (i<(num)); 
int r=munmap(&buffer[0],datos.st_size); 

return(n); 
} 

Merci à tous pour l'aide.

Questions connexes