c ++关闭用mmap读取的open()文件

问题描述 投票:1回答:1

我正在使用mmap()快速读取大文件,我的脚本基于这个问题的答案(Fast textfile reading in c++)。

我正在使用第二个版本来回答:

#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) {

然后使用以下命令获取main()函数中“f”对象中的文件内容:

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()函数的末尾,它确实没有任何改变。

非常感谢您的任何帮助!

编辑:

在我收到的重要建议之后,我使用mmap()和std :: cin()对不同的方法进行了一些性能比较,请查看:fast file reading in C++, comparison of different strategies with mmap() and std::cin() results interpretation的结果

c++ linux file mmap
1个回答
0
投票

Limit to the number of concurrently open files

可以想象,保持文件打开会消耗资源。因此,在任何情况下,对系统上的打开文件描述符的数量都有实际限制。这就是强烈建议您关闭不再需要的文件的原因。

确切的限制取决于操作系统和配置。如果您想了解更多信息,那么这类问题已经有很多答案可供选择。

Special case of mmap

显然,使用mmap()你打开一个文件。并且在循环风险中重复这样做会迟早达到致命文件描述限制,正如您可能会遇到的那样。

尝试关闭文件的想法并不错。问题是它不起作用。这在POSIX documentation中指定:

mmap()函数为与文件描述符fildes关联的文件添加了一个额外的引用,该文件描述符fildes不会被该文件描述符上的后续close()删除。当没有更多映射到文件时,将删除此引用。

为什么?因为mmap()以特殊的方式将文件链接到系统中的virtual memory management。只要您使用分配的地址范围,就会需要此文件。

那么如何删除这些映射呢?答案是使用munmap()

函数munmap()删除包含从addr开始并继续len字节的进程的地址空间的任何部分的整个页面的任何映射。

当然,close()是您不再需要的文件描述符。一个谨慎的方法是在munmap()之后关闭,但原则上,至少在POSIX兼容系统上,它应该不重要when you're closing。不过,检查您的最新操作系统文档是否安全:-)

*注意:file mapping也可在Windows上使用;如果存在剩余的映射,则documentation about closing the handles对潜在的内存泄漏是不明确的。这就是为什么我建议在收盘时刻谨慎。 *

© www.soinside.com 2019 - 2024. All rights reserved.