Проекция файла в память с использованием mmap - PullRequest
0 голосов
/ 15 ноября 2009

Я пытаюсь спроецировать файл в память для работы с ним. Файл содержит структуру, поэтому я пытаюсь использовать указатель на начало одной структуры, а затем прочитать ее и изменить некоторую переменную. Проблема в том, что время выполнения велико, и я полагаю, что при использовании mmap время будет меньше. Это код, любое предложение?

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

int revisanotas(int fd)
{
int nbytes=1;
int nbytese=0;
int i=0;
int n=0;
struct stat datos;
fstat(fd, &datos);
evaluacion buf;
evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
int actual = read(fd,buffer,datos.st_size);
{
i++;
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5)
{
n=n+1;
printf("Notamedia = %f\n",buffer[i].notamedia);

buffer[i].notamedia=5;
}

}while (i<(datos.st_size/(sizeof(evaluacion))));
return

Ответы [ 5 ]

2 голосов
/ 15 ноября 2009

Звонок на read() не нужен. Mmap() отображает содержимое файла в память для вас - поэтому обычно это быстрее, чем чтение всего файла с использованием read(). Вы должны быть в состоянии удалить звонок на read() в целом. Однако с вашим кодом есть и другие проблемы.

Если вы хотите, чтобы изменения действительно отображались в файле на диске, вам следует позвонить msync(buffer, dataos.st_size, MS_SYNC). Когда вы закончите, позвоните munmap(buffer, dataos.st_size), чтобы освободить сегмент общей памяти. Думайте о msync() как о разделяемой памяти, эквивалентной fflush(), а munmap() похож на close(). Основное различие между munmap() и close() заключается в том, что первый не очищает буферы и не синхронизируется с диском, поэтому вы должны сделать это самостоятельно.

2 голосов
/ 15 ноября 2009

Ну, во-первых, пожалуйста, сообщите нам, как определяется evaluacion, и поместите туда do, который соответствует while; Я предполагаю, что это сразу после строки "int actual".

Во-вторых, похоже, вы вызываете mmap () чаще, чем нужно; как часто revisanotas() вызывается с тем же fd? Сам вызов mmap медленный, как malloc; скорость - это когда вы используете сопоставленный файл, в этом случае данные указываются как buffer.

В-третьих, вычислите datos.st_size/(sizeof(evaluacion)) один раз вне цикла и измените предложение while для сравнения с ним. Текущий код выглядит так, как будто он выполняет деление один раз за итерацию в цикле, и деление происходит медленно.

Посмотрите, поможет ли это кому-нибудь.

0 голосов
/ 15 ноября 2009

Я думаю, что сейчас работает :), код выглядит следующим образом. Пожалуйста, прокомментируйте, если вы видите что-то не так:

int revisanotas(int fd)
{
int i=0;
int n=0;
struct stat datos;
fstat(fd, &datos);
int num=datos.st_size/(sizeof(evaluacion));

evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
do
{
i++;
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5)
{
n=n+1;
buffer[i].notamedia=5;
}

}while (i<(num));
int r=munmap(&buffer[0],datos.st_size);

return(n);
}

Спасибо всем за помощь.

0 голосов
/ 15 ноября 2009

Думаю, я добился определенного прогресса, но, похоже, я не изменяю файл. Если я запускаю программу один раз, она обнаруживает 32 измененные переменные, но если я дважды запускаю то же самое, когда предполагается изменить:

Время исполнения сейчас неплохое, я думаю

int revisanotas(int fd)
{
int i=0;
int n=0;
struct stat datos;
fstat(fd, &datos);
int num=datos.st_size/(sizeof(evaluacion));
evaluacion buf;
evaluacion* buffer=mmap(0,datos.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
do
{
i++;
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5)
{
n=n+1;

buffer[i].notamedia=5;
}
msync(&buffer[i],sizeof(buffer[i]),MS_SYNC);
}while (i<(num));
munmap(buffer,datos.st_size);
return(n);
}
0 голосов
/ 15 ноября 2009
Thanks mike for the answer, the struct is something like this and it's defined in a header file: 

struct evaluacion 
{ char id[16]; 
 char apellido1[32]; 
char apellido2[32]; 
char name[32]; float nota1p; 
float nota2p; 
float notamedia; 
char photofilename[20]; 
int photosize; 
char photodata[16000]; 
}; 

Там только один fd, открыт только один файл, но внутри него много структур

...