繁体   English   中英

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

[英]c++ close a open() file read with mmap

我正在使用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) {

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

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

并在一段时间后从main()在文件名列表的循环上调用它main()

open: Too many open files

我想在处理文件后会有一种关闭open()调用的方法,但是我无法弄清楚如何以及在哪里正确放置它。 我试过了:

int fc = close(fd);

在readFile()函数的末尾,但它并没有改变。

提前非常感谢您的帮助!

编辑

在收到重要建议后,我使用mmap()和std :: cin()对不同方法进行了性能比较,签出: 使用C ++快速读取文件,使用mmap()和std :: cin()对不同策略进行了比较结果解释

限制同时打开的文件数

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

确切的限制取决于操作系统和配置。 如果您想了解更多,这种问题已经有很多答案了。

mmap的特例

显然,使用mmap()可以打开一个文件。 如此反复地循环执行,可能会早晚达到致命文件描述限制,这是您可能会遇到的危险。

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

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

为什么呢 因为mmap()以特殊方式将文件链接到系统中的虚拟内存管理 只要使用文件分配的地址范围,就需要该文件。

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

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

当然, close()不再需要的文件描述符。 谨慎的方法是在munmap()之后关闭,但原则上,至少在POSIX兼容系统上, 关闭时不要紧。 不过,为了安全起见,请查看最新的OS文档:-)

*注意: 文件映射在Windows上也可用; 如果存在剩余的映射,则有关关闭句柄文档对于潜在的内存泄漏是模棱两可的。 这就是为什么我建议您在结束时保持谨慎。 *

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM