2012-04-23 87 views
1

我想打开大小为100GB的文件,并且每次都使用文件映射按块大小读取数据块。当偏移量大于2GB时,它始终会开始映射任何内容。我认为我可能是不支持64位寻址的功能。但在添加大文件支持(包括大文件支持定义,大文件打开选项以及使用命令-D_FILE_OFFSET_BITS = 64 -D_LARGE_FILE编译)之后。但是,同样的问题仍然存在。下面是简化的代码:大文件(100GB)通过使用内存映射的块来打开和读取块大小

#define _LARGEFILE_SOURCE 
#define _LARGEFILE64_SOURCE 
#define _FILE_OFFSET_BITS 64 
#include <math.h> 
#include <time.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include<fcntl.h> 
#include<unistd.h> 
#include<sys/stat.h> 
#include<sys/time.h> 
#include<sys/mman.h> 
#include<sys/types.h> 

#define PERMS 0600 

int total_piece, PAGE, buffer, share, offset, count, chunk; 

void get_size(char * strFileName) 
{ 
    struct stat temp; 
    stat(strFileName, &temp); 

    PAGE = getpagesize();    
    total_piece = temp.st_size/PAGE; 
    chunk = 1024*1024*1024*0.4/PAGE; 

    if (temp.st_size%PAGE!=0)  
    total_piece++; 
} 

char * 
mmaping (char *source) 
{ 
    int src; 
    char *sm; 
    struct stat statbuf; 

    if ((src = open (source, O_RDONLY)) < 0) //I thought error comes from this line. So I tried to use large file support as following. But still the same. 
    { 
     perror (" open source "); 
     exit (EXIT_FAILURE); 
    } 
/* 
    if ((src = open64(source, O_RDONLY|O_LARGEFILE, 0644))<0) 
    { 
     perror (" open source "); 
     exit (EXIT_FAILURE); 
    } 
*/ 
    if (fstat (src, &statbuf) < 0) 
    { 
     perror (" fstat source "); 
     exit (EXIT_FAILURE); 
    } 

    printf("share->%d PAGES per node\n",share); 

    if (share>=chunk) 
    buffer = chunk; 
    else 
    buffer = share; 

    printf("total pieces->%d\n",total_piece); 
    printf("data left->%d\n",share); 
    printf("buffer size->%d\n",buffer); 
    printf("PAGE size->%d\n",PAGE); 

    sm = mmap (0,buffer*PAGE, PROT_READ, MAP_SHARED | MAP_NORESERVE,src, offset*PAGE); 

    if (MAP_FAILED == sm) 
    { 
     perror (" mmap source "); 
     exit (EXIT_FAILURE); 
    } 

    return sm; 
} 

main(int argc, char**argv){ 

    get_size(argv[1]); 

    share = total_piece; 

    offset = 0; 

    while (share>0) 
    { 

     char *x = mmaping(argv[1]); 

     printf("data->%0.30s\n",x); //bus error will occur when offset reaches 2GiB, which proves my thought: it maps   nothing. 

     munmap(x,buffer*PAGE); 

     share-=buffer; 

     offset+=buffer; 

    } 

    return 0; 
} 

任何人都可以是很好,帮助我吗?

+0

你只想读取文件,为什么映射? – UmNyobe 2012-04-23 09:06:14

+1

为什么1024 * 1024 * 1024 * 0.4'而不是更清晰(更“正确”)1024 * 1024 * 400'? – 2012-04-23 09:08:12

+0

@UmNyobe老兄我想读取文件中的数据并对其进行处理。就我而言,速度非常重要,这就是为什么我使用映射。 – tzcoolman 2012-04-23 09:14:38

回答

4

当然,在Linux上32位的“int”类型变量的大小不足以包含100 GB文件的字节大小。对于文件大小/偏移量,您需要使用类型“off_t”(此时,在您启用LFS支持时,它是off64_t的一个别名,一个带符号的64位整数)。

类似地,mmap的“length”参数的类型是size_t,而不是int。

为了使代码可移植到32位和64位目标上,使用和不使用LFS,您需要注意哪些整数类型应该在哪里使用。

+1

精髓:'int'从来不是一个好主意,因为它永远不会告诉源代码读者完整的故事。 – 2012-04-23 09:56:39

+0

@janneb OMFG ......我应该注意到这一点。多谢老兄! – tzcoolman 2012-04-23 12:31:12