La lecture d'un fichier à chaîne avec mmap
J'essaie de lire un fichier à l'aide de la chaîne de mmap.
J'étais en suivant cet exemple: http://www.lemoda.net/c/mmap-example/index.html
Mon code ressemble à ceci
unsigned char *f;
int size;
int main(int argc, char const *argv[])
{
struct stat s;
const char * file_name = argv[1];
int fd = open (argv[1], O_RDONLY);
/* Get the size of the file. */
int status = fstat (fd, & s);
size = s.st_size;
f = (char *) mmap (0, size, PROT_READ, 0, fd, 0);
for (i = 0; i < size; i++) {
char c;
c = f[i];
putchar(c);
}
return 0;
}
Mais je reçois toujours une segemation défaut lors de l'accès à f[i].
Ce que je fais mal?
Vous n'avez pas de vérifier les valeurs de retour de
open
et mmap
. Ce qui se passe si vous le faites?OriginalL'auteur arnoapp | 2013-12-08
Vous devez vous connecter pour publier un commentaire.
strace
est votre ami ici:$ strace ./mmap-example mmap-example.c
La
mmap
homme page vous indique tout ce que vous devez savoir 😉EINVAL
Nous n'aimons pasaddr
,length
, ouoffset
(par exemple, ils sont tropgrand, ou non alignée sur une frontière de page).
EINVAL
(depuis Linux 2.6.12)length
était de 0.EINVAL
flags
contenait niMAP_PRIVATE
ouMAP_SHARED
, oucontenait à la fois de ces valeurs.
La
-EINVAL
erreur est causée par des drapeaux qui ne peut pas être 0. SoitMAP_PRIVATE
ouMAP_SHARED
qui sera choisi. J'ai été capable de le faire fonctionner en utilisantMAP_PRIVATE
sur Linux, x86-64.Donc, vous avez juste à ajouter MAP_PRIVATE à
mmap()
:NOTE: Ma première réponse n'inclure une autre cause possible de la
EINVAL
:Ce n'est pas réellement nécessaire, mais vous devez prendre en compte que de toute façon, la cartographie sera toujours effectuée en multiples du système de la taille de la page, donc si vous souhaitez calculer la quantité de mémoire réellement disponible à travers le pointeur retourné, mise à jour
size
comme ceci:f
estNULL
sur le crash de la ligne, ce qui implique que l'appel àmmap
a échoué.size
n'a pas besoin d'être un multiple de la taille de la page; je pense que l'OP de la question est que soitMAP_PRIVATE
deMAP_SHARED
doit être spécifié. À partir de pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html: "La mise en œuvre effectue le mappage des opérations sur des pages entières. Ainsi, alors que l'argument len n'a pas besoin de répondre à une taille ou d'un alignement de la contrainte, la mise en œuvre comprendra, dans toute opération de cartographie, toute partielle page spécifiée par la gamme[pa, pa + len)
."Vous avez raison: j'ai mal lu les informations sur ce qu'ont à être aligné à la limite de la page. C'est ce que la page de man de mmap dit à ce sujet: EINVAL Nous n'aimons pas l'addr, la longueur, ou la compensation (par exemple, ils sont trop gros, ou non alignée sur une frontière de page). EINVAL (depuis Linux 2.6.12) longueur est de 0. EINVAL indicateurs figurent ni MAP_PRIVATE ou MAP_SHARED, ou de contenu de ces deux valeurs. Je vais mettre à jour la réponse 🙂
offset must be a multiple of the page size as returned by sysconf(_SC_PAGE_SIZE).
. J'utilise le bit à mettre en œuvre.pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
OriginalL'auteur mcleod_ideafix