2016-01-08 3 views
1

Im пытается работать с чтением mmap из файла в цикле, У меня есть файл содержит информацию о 3 частях, первая часть размером 3 * sizeof (double), вторая также в размере 3 * sizeof (double), а третий с размером sizeof (double). В первой части файла у меня HEADER размером 32768 байт. Файл организован:mmap из файла в цикле

ГОЛОВКА Часть (1), часть (1) .... Часть (1) || Часть (2), часть (2) .... Часть (2) || Часть (3), часть (3) .... Часть (3) |

Каждая часть у меня есть 100 раз. Я хочу работать каждый раз с 30 частями (10 частей от каждой части).

Я попробовал этот код:

void readingFile(FILE *file, double *a, double *b, double *c, int start, int end, int chunksz, long total) 
{ 
    int i = 0; 
    int size = end - start + 1; 
    int fd; 
    fd = fileno(file); 
    off_t fullsize = lseek(fd,SEEK_CUR,SEEK_END); //getting the file size 
    fullsize-=1;//the lseek gives one more byte, its ok! 
    unsigned long summ = (unsigned long)(start-1)*chunksz; //chunk is 56 
    summ+=(unsigned long)HEADER_SIZE;//offset the header size 
    unsigned long paramm=(unsigned long)((unsigned long)summ/(unsigned long)(sysconf(_SC_PAGE_SIZE))); 
    unsigned long param = floor(paramm); 
    void *buf=NULL; 
    buf =mmap(NULL,fullsize , PROT_READ, MAP_PRIVATE , fd, param*sysconf(_SC_PAGE_SIZE)); 
    if(buf==MAP_FAILED) 
    { 
     printf("we have an error\n"); 
    } 
    unsigned long gapp = (sysconf(_SC_PAGE_SIZE))*param; 
    unsigned long gap =summ-gapp; 
    buf+=gap; 
    memcpy(a,buf,3*sizeof(double)*size); 
    buf+=(unsigned long)((long)total-(start-1))*3*sizeof(double); 
    buf+=((start-1)*3*sizeof(double)); 
    memcpy(b,buf,3*sizeof(double)*size); 
    buf+=(unsigned long)((long)total-(start-1))*3*sizeof(double); 
    buf+=((start-1)*sizeof(double)); 
    memcpy(c,buf,sizeof(double)*size); 
    munmap(buf, fullsize); 
    return; 
} 

Где-то в пути у меня есть Переполнение и программа разваливается! Каждый раз, когда вызываемая функция, новая память распределяется должным образом на a, b, c. Что здесь? Процесс разбился на итерации № 14 в строке:

memcpy(c,buf,sizeof(double)*size); 

Спасибо!

+1

«Где-то в пути, у меня переполнение». Используйте отладчик, чтобы точно узнать «где-то». – kaylum

+1

Если вы получаете файловый дескриптор, вы можете использовать 'fstat()'] (http://pubs.opengroup.org/onlinepubs/009695399/functions/fstat.html), чтобы получить размер файла вместо 'lseek() '. Использование 'lseek()' в файле, уже открывшемся с помощью 'FILE * ', может привести к поломке вещей, если данные' FILE * 'ожидают, что смещение файла будет там, где оно осталось. Вы также сопоставляете количество байтов, равное полному размеру файла - **, но с ненулевым смещением **. И если ваш вызов 'mmap()' терпит неудачу, вам нужно сделать что-то другое, кроме как распечатать ошибку, а затем продолжить работать, как ничего не произошло. –

+0

Файл открыт, и ошибка не является дуэтом для вызова mmap. – raptor0102

ответ

1

Я знаю, что ответ на вопрос с исходным кодом не знаком. Но я пытаюсь объяснить, что полезно для mmap. В основном mmap использует возможности ядра для загрузки (и записи) содержимого файла в область памяти. поэтому нам не нужно часто вызывать чтение/поиск, что может сделать ваше приложение более эффективным. В другой стороны, это комфортабельное решение для доступа к данным непосредственно, просто увидеть код:

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

struct mapping 
{ 
     void* start_addr; 
     size_t length; 
     int fd; 
}; 

struct mapping* map_file(const char* file) 
{ 
     struct mapping* ret = malloc(sizeof(struct mapping)); 
     if(NULL == ret) 
     { 
       printf("Can't allocate memory for struct mapping.\n"); 
       return NULL; 
     } 

     ret->fd = open(file, O_RDONLY); 
     if(0 > ret->fd) 
     { 
       perror("can't open specified file."); 
       free(ret); 
       return NULL; 
     } 

     struct stat fs; 
     if(0 != fstat(ret->fd, &fs)) 
     { 
       perror("can't specify file size."); 
       close(ret->fd); 
       free(ret); 
       return NULL; 
     } 

     ret->length = fs.st_size; 

     //offset means offset in file 
     ret->start_addr = mmap(NULL, ret->length, PROT_READ, MAP_PRIVATE, ret->fd, 0); 
     if(MAP_FAILED == ret->start_addr) 
     { 
       perror("Mapping file failed."); 
       close(ret->fd); 
       free(ret); 
       return NULL; 
     } 

     return ret; 
} 

//returns zero on success and free the `struct mapping` data 
int unmap_file(struct mapping* mmf) 
{ 
     //note that now we use read only mapping 
     //if you want to write this memory pages 
     //before detach maybe you have to call: 
     //msync(mmf->start_addr, mmf->length, MS_SYNC); 
     // avoid data loss (write all dirty page into file). 

     if(NULL != mmf->start_addr) 
     { 
       if(0 != munmap(mmf->start_addr, mmf->length)) 
       { 
         perror("Can't munmap file."); 
         return 1; 
       } 
     } 

     mmf->start_addr = NULL; 
     if(-1 != mmf->fd) 
     { 
       if(0 != close(mmf->fd)) 
       { 
         perror("can't close file descriptor."); 
         return 2; 
       } 
     } 

     free(mmf); 

     return 0; 
} 

// for test#define MAGIC_START_INDEX 0 
#define MAGIC_START_INDEX 32768 

int main(int arg_length, char** args) 
{ 
     if(arg_length < 2) 
     { 
       printf("No input file specified.\n"); 
       exit(1); 
     } 

     int i = 0; 
     //first argument is the name of program 
     while(++i < arg_length) 
     { 
       struct mapping* mmf = map_file(args[i]); 
       if(NULL == mmf) 
       { 
         printf("can't use %s for input file\n", args[i]); 
         continue; 
       } 

       if(mmf->length > MAGIC_START_INDEX) 
       { 
         //upper base 
         int max_index = (mmf->length - MAGIC_START_INDEX)/sizeof(double); 

         //an offset alias for start memory address 
         double* data = ((double*)(mmf->start_addr + MAGIC_START_INDEX)); 

         int ni = 0; 
         while(ni+2 < max_index) 
         { 
           printf("num0: %f, num1: %f, num2: %f\n", data[ni], data[ni+1], data[ni+2]); 
           ni += 3; 
         } 
       } 
       else 
       { 
         printf("File: %s has no valuable data.", args[i]); 
       } 

       unmap_file(mmf); 
     } 
} 

В основном, вы видите, мы можем использовать непосредственно адрес памяти, а не повторять операцию чтение. Это пример кода, который я копировал (сопоставление связанных данных, хранящихся в структуре и связанных с ними функциях, заботится о создании/выпуске сопоставления файлов). Это чтение может быть более ленивым, просто открыть файл, прочитать размер (fstat), если я есть ценные данные, использовать MMAP это смещение параметра, чтобы пропустить раздел заголовка в файле:

double[] data = (double*)(mmap(NULL, file_length, PROT_READ, MAP_PRIVATE, fd, MAGIC_START_INDEX)); //TODO check null. 

и вы получите «мгновенное «доступ к данным.