добавление в отображенный в память файл - PullRequest
22 голосов
/ 16 декабря 2010

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

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

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

Есть ли другие подходы?

Doest Boost поможет с этим?

Ответы [ 5 ]

22 голосов
/ 16 декабря 2010

Boost.IOStreams имеет только фиксированный размер отображенных в память файлов , так что это не поможет с вашей конкретной проблемой 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);
}

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

16 голосов
/ 19 августа 2012

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

2 голосов
/ 16 декабря 2010

Глядя на справочную страницу для mremap , это должно быть возможно.

0 голосов
/ 17 ноября 2016

Если вы используете 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);
}
0 голосов
/ 06 января 2015

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

...