2010-12-16 4 views
21

Я постоянно добавляю файл котировок акций (ints, longs, doubles и т. Д.). У меня этот файл отображается в память с помощью mmap., добавляющий к файлу с отображением памяти

Каков наиболее эффективный способ сделать недавно добавленные данные доступными как часть отображения памяти?

Я понимаю, что я могу снова открыть файл (новый файловый дескриптор), а затем mmap его, чтобы получить новые данные, но это кажется неэффективным. Другим подходом, который мне предлагалось, является предварительное выделение файла в 1 мб кусках, запись в определенную позицию до достижения конца, затем ftruncate файл до + 1mb.

Существуют ли другие подходы?

Помогите справиться с этим?

ответ

17

Boost.IOStreams имеет фиксированный размер только memory mapped files, поэтому он не поможет с вашей конкретной проблемой. Linux имеет интерфейс mremap, который работает следующим образом:

void *new_mapping = mremap(mapping, size, size + GROWTH, MREMAP_MAYMOVE); 
if (new_mapping == MAP_FAILED) 
    // handle error 
mapping = new_mapping; 

Это непереносимое, однако (и плохо документированный). Mac OS X, похоже, не имеет mremap.

В любом случае, вам не нужно открыть файл, просто munmap его и mmap снова:

void *append(int fd, char const *data, size_t nbytes, void *map, size_t &len) 
{ 
    // TODO: check for errors here! 
    ssize_t written = write(fd, data, nbytes); 
    munmap(map, len); 
    len += written; 
    return mmap(NULL, len, PROT_READ, 0, fd, 0); 
} 

схема предварительного распределения может быть очень полезным здесь. Обязательно отслеживайте фактическую длину файла и обрезайте его еще раз перед закрытием.

2

Рассматривая man page for mremap, это должно быть возможно.

+1

mremap является специфичным для Linux. – 2010-12-16 15:16:13

14

Я знаю, что ответ уже принят, но, возможно, это поможет кому-то другому, если я дам свой ответ. Выделите большой файл загодя, скажем, 10 GiB. Создайте три из этих файлов загодя, я называю их томами. Следите за своим последним известным местоположением где-то, как в заголовке, другом файле и т. Д., А затем продолжайте добавлять с этой точки. Если вы достигнете максимального размера файла и перейдете из комнатного переключателя на следующий том. Если больше нет томов, создайте другой том. Обратите внимание, что вы, вероятно, сделаете это несколько томов вперед, чтобы не блокировать свои приложения, ожидая создания нового тома. Именно так мы реализуем его, где я работаю для хранения непрерывного входящего видео/аудио в системе DVR для наблюдения. Мы не теряем места для хранения имен файлов для видеороликов, поэтому мы не используем настоящую файловую систему, и вместо этого мы идем плоским файлом, и мы просто отслеживаем смещения, информацию о кадре (fps, тип кадра, ширину/высоту и т. Д.).), записанное время и канал камеры. Для вас пространство для хранения дешево для той работы, которую вы делаете, тогда как ваше время неоценимо. Итак, хватайте столько, сколько хотите раньше времени. Вы в основном реализуете свою собственную файловую систему, оптимизированную для ваших нужд. Потребности в общем использовании файловых систем - это не то же самое, что нам нужно в других областях.

0

Мои 5центы, но они более специфичны. Сделайте обычный файл, но mmap огромный размер - например, файл скажет 100K, но mmap 1GB или больше. Затем вы можете безопасно получить доступ ко всем размерам файлов. Доступ к размеру файла приведет к ошибке. Если вы находитесь на 32-битной ОС, просто не делайте mmap слишком большим, потому что он будет есть ваше адресное пространство.

0

Если вы используете boost/iostreams/device/mapped_file.hpp на окнах:

boost::filesystem::resize_file бросает исключение, если объект сопоставления чтения открыт, из-за отсутствия прав общего доступа. Вместо этого используйте windows-api для изменения размера файла на диске, и чтение mapped_file s может быть открыто.

bool resize_file_wapi(string path, __int64 new_file_size) //boost::uintmax_t size 
{ 
    HANDLE handle = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 0); 
    LARGE_INTEGER sz; 
    sz.QuadPart = new_file_size; 

    return handle != INVALID_HANDLE_VALUE 
    && ::SetFilePointerEx(handle, sz, 0, FILE_BEGIN) 
    && ::SetEndOfFile(handle) 
    && ::CloseHandle(handle); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^