les fichiers mappés en mémoire
J'ai écrit un code pour écrire le contenu à l'mappés en mémoire tampon qui mappés à l'aide de la mmap() de l'appel système.
Après j'ai fait quelques changements dans le mappés en mémoire tampon,puis j'ai appelé le msync().Elle devrait mettre à jour le fichier sur disque.
Mais,Il n'a pas procédé à des changements dans le fichier sur le disque.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
#define FILEMODE S_IRWXU | S_IRGRP | S_IROTH
#define MAX 150
main(int argc,char *argv[])
{
int fd,ret,len;
long int len_file;
struct stat st;
char *addr;
char buf[MAX];
if(argc > 1)
{
if((fd = open(argv[1],O_RDWR | O_APPEND | O_CREAT ,FILEMODE)) < 0)
perror("Error in file opening");
if((ret=fstat(fd,&st)) < 0)
perror("Error in fstat");
len_file = st.st_size;
/*len_file having the total length of the file(fd).*/
if((addr=mmap(NULL,len_file,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0)) == MAP_FAILED)
perror("Error in mmap");
len = len_file;
while((fgets(buf,MAX,stdin)) != NULL)
{
strcat(addr+len,buf);
printf( "Val:%s\n",addr ) ; //Checking purpose
len = len + (strlen(buf));
}
if((msync(addr,len,MS_SYNC)) < 0)
perror("Error in msync");
if( munmap(addr,len) == -1)
printf("Error:\n");
printf("addr %p\n",addr);
}
else
{
printf("Usage a.out <filename>\n");
}
}
OriginalL'auteur sat | 2011-12-07
Vous devez vous connecter pour publier un commentaire.
Si vous souhaitez que vos modifications soient répercutées dans le fichier du disque dur, vous devez mapper le fichier en tant que
MAP_SHARED
, pasMAP_PRIVATE
.En outre, vous ne pouvez pas étendre le fichier, il suffit d'écrire au-delà de la fin de la cartographie. Vous devez utiliser
ftruncate()
pour étendre le fichier à la nouvelle taille, puis modifiez le mappage d'inclure la nouvelle partie du fichier. Le portable de façon à modifier le mappage est de détacher la cartographie puis le recréer avec la nouvelle taille; sur Linux, vous pouvez à la place utilisermremap()
.Votre
len
etlen_file
variables doivent être de typesize_t
, et vous devez l'utilisermemcpy()
plutôt questrcat()
, car vous savez exactement la longueur de la chaîne, exactement là où vous voulez le copier, et vous ne pas souhaitez copier le null-terminator.La suite de la modification de votre code fonctionne sur Linux (en utilisant
mremap()
) :Super..Il fonctionne très bien..je vous Remercie.
N'est-ce pas rater un appel à close(fd) ?
Oui - j'avais juste fait le minimum de modifications au code de la question, mais vous avez raison -
close()
devrait être appelée de façon à ce que nous pouvons vérifier pour un retour d'erreur.OriginalL'auteur caf
Notez que si vous avez fourni une cartographie pour le fichier qui est exactement la taille du fichier. Si vous créez le fichier dans votre appel à
open(2)
, il aura une longueur de0
, et je ne serais pas surpris si le noyau n'est pas la peine de configurer le type de mappage de la mémoire à partir d'un0
longueur de la cartographie. (Peut-être que c'est? Je n'ai jamais essayé...)Je conseille
ftruncate(2)
pour augmenter la longueur de votre fichier avant exécution de la cartographie. (À noter que l'extension des fichiers à l'aideftruncate(2)
n'est pas très portable; pas toutes les plates-formes de fournir à l'extension des fonctionnalités et pas tous les pilotes de système de fichiers de support de l'extension des fonctionnalités. Consultez votre système de page de manuel pour plus de détails.)Vous devez utiliser le
MAP_SHARED
cartographie pour votre fichier de modifications qui doivent être enregistrés sur le disque.Votre utilisation de
perror(3)
n'est pas tout à fait exact;perror(3)
sera pas mettre fin à votre programme, donc, il va continuer à exécuter avec des hypothèses erronées:Devrait lire:
(Ou
exit(EXIT_FAILURE)
si vous voulez être plus portable -- je trouve qu'un peu plus de pression sur les yeux, mais je vis dans Linux-land.)strcat(3)
s'attend à trouver un ASCII NUL caractère (octet de valeur0x00
, C représentation'\0'
) -- l'habitude C en fin de chaîne de marqueur -- à la fin de ladest
chaîne. Votre fichier ne comporte pas d'un ASCII NUL si vous le créez dans ce programme, sa longueur est égale à zéro, après tout-et je ne sais pas les conséquences de la tentative de lecture d'un zéro octet fichier viammap(2)
. Si le fichier existe déjà et a des données qu'il contient, il probablement n'a pas un ASCII NUL codée dans le fichier.strcat(3)
est presque certainement le mauvais outil pour écrire dans votre fichier. (Personne ne veut ASCII NULs dans leurs fichiers de toute façon.) Essayezmemcpy(3)
à la place.chattr +a THEFILE
dans un shell.O_APPEND
dicte le comportement de l'écriture de l'appel système, mais pas les mappages de mémoire. -- modifiée pour supprimer lesMAP_SHARED
peu comme un résultat. 🙂OriginalL'auteur sarnold