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 Réponses :
existe une sorte de quota par utilisateur, limitant la quantité de mémoire disponible pour un processus utilisateur? p>
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 ...
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. ). p>
Cela s'intégrerait à votre espace adressable, mais pourrait ne pas correspondre (du moins contiguë) dans la mémoire physique. P>
Si quelqu'un en sait plus sur la façon dont Linux, je serais intéressé à en entendre parler. P>
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 () code>.
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 CODE> Réglez-le sur 1,5 To et mon appel MMAP () a réussi. Merci, Bmargulies , pour l'asseinte à essayer Ulimit -A! P>
Et, apparemment, je peux définir la valeur souhaitée (qui peut être «illimité») dans / etc / profil pour le rendre persistant.
En tant que point d'intérêt, votre programme travaille pour moi jusqu'à une taille de 256 Go (
1 << 38 code>), avec quelque chose de retournement plus élevéeinval code>. 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 ...