2010-01-29 10 views
1

Je suis novice en architecture 64 bits. Pourriez-vous me dire quelle est la taille de fichier MAX supportée par le mappage de fichiers dans une machine linux 64 bits. Je veux ouvrir plus de 20 Go de fichiers par mappage de fichiers, est-il disponible?Quelle est la taille de mappage de fichier maximale dans la machine 64 bits

J'écris un exemple de code. Mais il provoque Erreur de bus quand je reçois la valeur du pointeur en GBSIZE offset:

unsigned char* pCur = pBegin + GBSIZE; 
//pBegin is the pointer returned by mmap 
printf("%c",*pCur); 

BTW, printf("%c",*pBegin); fonctionne très bien. et mes tailles d'adresse: 38 bits de physique, 48 bits virtuels

Voici le code complet:

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

//#define FILEPATH "smallfile" 
#define FILEPATH "bigfile" 
#define GBSIZE (1024L*1024L*1024L) 
#define TBSIZE (1024L*GBSIZE) 
#define NUMSIZE (20L * GBSIZE) 
//#define NUMSIZE (10) 
#define FILESIZE (NUMINTS * sizeof(int)) 

int main(int argc, char *argv[]) 
{ 
    int i; 
    int fd; 
    unsigned char *pBegin; 

    fd = open(FILEPATH, O_RDONLY); 
     if (fd == -1) { 
     perror("Error opening file for reading"); 
     exit(EXIT_FAILURE); 
    } 

    pBegin = mmap(0, NUMSIZE, PROT_READ, MAP_SHARED, fd, 0); 
    if (pBegin == MAP_FAILED) { 
     close(fd); 
     perror("Error mmapping the file"); 
     exit(EXIT_FAILURE); 
    } 

    /** ERROR happens here!!! **/ 
    unsigned char* pCur = pBegin + GBSIZE; 
    printf("%c",*pCur); 

    if (munmap(pBegin, NUMSIZE) == -1) { 
     perror("Error un-mmapping the file"); 
    } 
    close(fd); 
    return 0; 
} 
+0

'pszPointer' semble être non initialisé. Vous obtiendrez de meilleures réponses si vous postez un programme complet qui démontre le problème - de préférence comme une nouvelle question. – caf

+0

merci, j'ai fait une erreur stupide. –

+0

Concernant l'erreur de bus, POSIX déclare: "Les références dans la plage d'adresses commençant à pa et continuant pour des octets len à des pages entières suivant la fin d'un objet doivent aboutir à la livraison d'un signal SIGBUS." http://www.opengroup.org/onlinepubs/9699919799/functions/mmap.html Si vous avez d'autres questions, postez une nouvelle question. – mark4o

Répondre

1

adresses 64 bits permettent de plusieurs ordres de grandeur plus de 20 Go.

5

De la page man mmap(2):

void *mmap(void *addr, size_t length, int prot, int flags, 
       int fd, off_t offset); 

length est un size_t, qui sur les machines 64 bits est une longueur de 64 bits. Donc oui, vous pouvez théoriquement mapper un fichier de 20Go.

9

Bien que les pointeurs aient une largeur de 64 bits, la plupart des processeurs ne prennent pas réellement en charge les adresses virtuelles utilisant les 64 bits complets. Pour voir la taille des adresses virtuelles prises en charge par votre processeur, regardez /proc/cpuinfo (48 bits est typique).

grep "address sizes" /proc/cpuinfo 

De plus, la moitié de l'espace d'adressage virtuel est utilisé par le noyau et non disponible pour l'espace utilisateur - laissant dans l'implémentation actuelle de Linux 47 bits.

Cependant, même en tenant compte de cela, vous aurez toujours beaucoup de de pièce pour un fichier de 20GB. 47 bits en théorie signifie un espace d'adressage virtuel de 128 To.

+0

J'ai essayé de convertir un fichier de 20 Go en mappage de fichiers. mais il provoque l'erreur de bus quand j'obtiens la valeur du pointeur dans le décalage GBSIZE: unsigned char * pCur = pBegin + GBSIZE; // pBegin est le pointeur retourné par mmap printf ("% c", * pszPointer); BTW, "printf ("% c ", * pBegin);" fonctionne bien. –

+3

Si vous ajoutez le décalage au début du mappage, vous obtenez un pointeur sur l'octet AU-DELÀ de la fin du mappage. Par conséquent, une erreur de bus correspond exactement à ce que j'attendrais. – MarkR

1

(Cette réponse a été initialement modifiée dans la question par OP)

Vous avez demandé une carte 20GB sur un fichier qui est seulement 50 Mo en taille.

Comme décrit par the mmap man page, mmap réussit lorsque vous demandez la longueur trop grande, mais il donnera SIGBUS ou SIGSEGV lorsque vous essayez réellement de lire au-delà de la fin du fichier sous-jacent.

0

En accord avec MarkR, vous déréférencez une adresse invalide. J'ai modifié votre code pour utiliser les drapeaux TLB ÉNORMES comme suit.

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

#define MAP_HUGETLB  0x40000   /* create a huge page mapping */ 
#define MAP_HUGE_SHIFT 26 
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) 

#define KSIZE 1024L 
#define MSIZE (1024L*1024L) 
#define GSIZE (1024L*1024L*1024L) 
#define TSIZE (1024L*GSIZE) 

#define INIT_MEM 0 
// Fail on my MacBook Pro (Retina, 13-inch, Early 2015) 
// Darwin Kernel Version 16.5.0:x86_64 
// #define NUMSIZE (16L * TSIZE) 

// mmap ok; init: got killed; signal 9 
// #define NUMSIZE (8L * TSIZE) 

// Got killed signal 9 
// #define NUMSIZE (1L * TSIZE) 

// OK 
// #define NUMSIZE (200L * GSIZE) 

// OK 
#define NUMSIZE (20L * GSIZE) 
typedef unsigned long long ETYPE; 

#define MEMSIZE (NUMSIZE*sizeof(ETYPE)) 
#define PGSIZE (16*KSIZE) 

void init(ETYPE* ptr) { 
     *ptr = (ETYPE)ptr; 
} 

int verify(ETYPE* ptr) { 
     if (*ptr != (ETYPE)ptr) { 
       fprintf(stderr, "ERROR: 0x%016llx != %p.\n", *ptr, ptr); 
       return -1; 
     } 
     else { 
       fprintf(stdout, "OK: 0x%016llx = %p.\n", *ptr, ptr); 
     } 
     return 0; 
} 
int main(int argc, char *argv[]) 
{ 
    int i; 
    int fd; 
    ETYPE *pBegin; 

    int flags = MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_HUGE_1GB; 
    printf("mmap memory size:%lu GB\n", MEMSIZE/GSIZE); 
    pBegin = (ETYPE*) mmap(0, MEMSIZE, PROT_READ | PROT_WRITE, flags, -1, 0); 
    if (pBegin == MAP_FAILED) { 
     perror("Error mmapping the file"); 
     exit(EXIT_FAILURE); 
    } 

    ETYPE* pEnd = pBegin + NUMSIZE; 
    ETYPE* pCur = pBegin; 

#if INIT_MEM 
    while (pCur < pEnd) { 
      init(pCur); 
      // ++pCur; //slow if init all addresses. 
      pCur += (PGSIZE/sizeof(ETYPE)); 
    } 
#endif 

    init(&pBegin[0]); 
    init(&pBegin[NUMSIZE-1]); 

    verify(&pBegin[0]); 
    verify(&pBegin[NUMSIZE-1]); 

    if (munmap(pBegin, MEMSIZE) == -1) { 
     perror("Error un-mmapping the file"); 
    } 
    return 0; 
} 
Questions connexes