c ++ закрыть файл open (), прочитанный с помощью mmap - PullRequest
1 голос
/ 25 марта 2019

Я работаю с mmap () для быстрого чтения больших файлов, основывая свой сценарий на ответе на этот вопрос ( Быстрое чтение текстовых файлов в c ++ ).

Я использую вторую версию изsehe ответ:

#include <algorithm>
#include <iostream>
#include <cstring>

// for mmap:
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

const char* map_file(const char* fname, size_t& length);

int main()
{
    size_t length;
    auto f = map_file("test.cpp", length);
    auto l = f + length;

    uintmax_t m_numLines = 0;
    while (f && f!=l)
        if ((f = static_cast<const char*>(memchr(f, n, l-f))))
            m_numLines++, f++;

    std::cout << "m_numLines = " << m_numLines << "n";
}

void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}

const char* map_file(const char* fname, size_t& length)
{
    int fd = open(fname, O_RDONLY);
    if (fd == -1)
        handle_error("open");

    // obtain file size
    struct stat sb;
    if (fstat(fd, &sb) == -1)
        handle_error("fstat");

    length = sb.st_size;

    const char* addr = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u));
    if (addr == MAP_FAILED)
        handle_error("mmap");

    // TODO close fd at some point in time, call munmap(...)
    return addr;
}

и все работает просто замечательно.

Но если я реализую его по циклу из нескольких файлов (я просто изменяю имя функции main () на:

void readFile(std::string &nomeFile) {

, а затем получаю содержимое файла в объекте "f" вФункция main () с:

size_t length;
auto f = map_file(nomeFile.c_str(), length);
auto l = f + length;

и вызовом ее из main() в цикле по списку имен файлов), через некоторое время я получил:

open: Too many open files

Я думаю, что будетбыть способ закрыть вызов open () после работы с файлом, но я не могу понять, как и где его точно поместить.Я попытался:

int fc = close(fd);

в конце функции readFile (), но она ничего не изменила.

Заранее большое спасибо за любую помощь!

EDIT :

после важных предложений, которые я получил, я провел некоторое сравнение производительности с различными подходами с помощью mmap () и std :: cin (), проверьте: быстрое чтение файлов в C ++,сравнение различных стратегий с интерпретацией результатов mmap () и std :: cin () для результатов

1 Ответ

0 голосов
/ 26 марта 2019

Ограничение на количество одновременно открытых файлов

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

Точный предел зависит от ОС и конфигурации.Если вы хотите узнать больше, на этот вопрос уже есть много ответов.

Особый случай mmap

Очевидно, что при mmap() вы открываете файл.И, повторяя это в цикле, вы рискуете рано или поздно достичь предела фатального описания файла, как вы могли заметить.

Идея попытки закрыть файл неплоха.Проблема в том, что это не работает.Это указано в документации POSIX :

Функция mmap() добавляет дополнительную ссылку на файл, связанный с файлом дескриптора файла, который не удаляется последующим close() в этом дескрипторе файла.Эта ссылка удаляется, когда больше нет сопоставлений с файлом .

Почему?Потому что mmap() связывает файл особым образом с управлением виртуальной памятью в вашей системе.И этот файл будет нужен до тех пор, пока вы используете диапазон адресов, на который он был выделен.

Так как удалить эти сопоставления?Ответ заключается в использовании munmap():

Функция munmap() удаляет любые сопоставления для тех целых страниц, которые содержат любую часть адресного пространства процесса, начиная с адреса и адреса.продолжение для длинных байтов.

И, конечно, close() дескриптор файла, который вам больше не нужен.Благоразумным подходом было бы закрытие после munmap(), но в принципе, по крайней мере, в POSIX-совместимой системе, это не должно иметь значения , когда вы закрываете .Тем не менее, проверьте вашу последнюю документацию по ОС, чтобы быть в безопасности :-)

* Примечание: сопоставление файлов также доступно в Windows;документация о закрытии дескрипторов неоднозначна в отношении возможных утечек памяти, если остаются оставшиеся сопоставления.Вот почему я рекомендую осторожность в момент закрытия.*

...