9
votes

Pourquoi MMAP () échoue avec Enomem sur un fichier de race 1TB?

Je travaille avec de gros fichiers rares sur OpenSuse 11.2 x86_64. Lorsque j'essaie de mmap () un fichier de race 1 ToB, il échoue avec Enomem. J'aurais pensé que l'espace d'adresses 64 bits serait adéquat à la carte dans un téraoctet, mais cela ne semble pas. Expérimenter plus loin, un fichier de 1 Go fonctionne bien, mais un fichier de 2 Go (et tout ce qui est plus grand) échoue. Je suppose qu'il peut y avoir un réglage quelque part pour toges, mais une recherche étendue ne rentrait rien.

Voici quelques échantillons de code qui montre le problème - les indices? P>

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    char * filename = argv[1];
    int fd;
    off_t size = 1UL << 40; // 30 == 1GB, 40 == 1TB

    fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
    ftruncate(fd, size);
    printf("Created %ld byte sparse file\n", size);

    char * buffer = (char *)mmap(NULL, (size_t)size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ( buffer == MAP_FAILED ) {
        perror("mmap");
        exit(1);
    }
    printf("Done mmap - returned 0x0%lx\n", (unsigned long)buffer);

    strcpy( buffer, "cafebabe" );
    printf("Wrote to start\n");

    strcpy( buffer + (size - 9), "deadbeef" );
    printf("Wrote to end\n");

    if ( munmap(buffer, (size_t)size) < 0 ) {
        perror("munmap");
        exit(1);
    }
    close(fd);

    return 0;
}


3 commentaires

En tant que point d'intérêt, votre programme travaille pour moi jusqu'à une taille de 256 Go ( 1 << 38 ), avec quelque chose de retournement plus élevé einval . Ceci est sur RHEL4 (noyau 2.6.9-42.0.3ELSMP).


Qu'est-ce que Ulimit -a dit?


Merci, Bmargulies - C'était ça. Ulimit -a a signalé une mémoire virtuelle sous forme de 1804800 kbytes (un peu plus de 1,7 Go). ULIMIT -V 1610612736 (1.5TB) me permet de me laisse mmap mon fichier de race 1 ToB. Je vais répondre à ma propre question pour que je puisse "fermer" ça ...


3 Réponses :


2
votes

existe une sorte de quota par utilisateur, limitant la quantité de mémoire disponible pour un processus utilisateur?


1 commentaires

YEP - J'ai essayé la suggestion de Bmargulies de tentative d'Ulimit -a et qui a souligné la limite de processus "Mémoire virtuelle" comme le coupable - voir ma réponse ci-dessous ...



1
votes

Je suppose que le noyau a de la difficulté à affecter la mémoire qu'il doit suivre cette mappage de mémoire. Je ne sais pas à quel point les pages d'échantillonnage sont utilisées dans le noyau Linux (et je suppose que la majeure partie du fichier serait dans l'état d'échantillonnage la plupart du temps), mais cela peut finir par avoir besoin d'une entrée pour chaque page. de mémoire que le fichier prend dans une table. Étant donné que ce fichier pourrait être galeté par plus d'un processus, le noyau doit suivre le mappage du point de vue du processus, qui correspondrait à un autre point de vue, qui correspondrait au stockage secondaire (et inclure des champs pour le dispositif et l'emplacement. ).

Cela s'intégrerait à votre espace adressable, mais pourrait ne pas correspondre (du moins contiguë) dans la mémoire physique.

Si quelqu'un en sait plus sur la façon dont Linux, je serais intéressé à en entendre parler.


1 commentaires

Linux ne créera pas les PTES (entrées de la table de page) jusqu'à ce que ces pages soient réellement touchées. Tout ce qu'il fait lorsque vous créez le mappage consiste à créer une structure unique VMA (zone de mémoire virtuelle), qui contient essentiellement les informations du MMAP () .



14
votes

Le problème était que la limite de mémoire virtuelle pertra-process a été définie sur seulement 1,7 Go. ULIMIT -V 1610612736 Réglez-le sur 1,5 To et mon appel MMAP () a réussi. Merci, Bmargulies , pour l'asseinte à essayer Ulimit -A!


1 commentaires

Et, apparemment, je peux définir la valeur souhaitée (qui peut être «illimité») dans / etc / profil pour le rendre persistant.