gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:14:25 26 4
gpt4 key购买 nike

我正在使用 mmap() 快速读取大文件,我的脚本基于这个问题的答案 ( Fast textfile reading in 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() 调用它),过了一会儿我得到:

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为结果

最佳答案

并发打开文件数限制

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

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

mmap的特例

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

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

The mmap() function adds an extra reference to the file associated with the file descriptor fildes which is not removed by a subsequent close() on that file descriptor. This reference is removed when there are no more mappings to the file.

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

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

The function munmap() removes any mappings for those entire pages containing any part of the address space of the process starting at addr and continuing for len bytes.

当然,close() 您不再需要的文件描述符。一种谨慎的方法是在 munmap() 之后关闭,但原则上,至少在符合 POSIX 的系统上,这应该无关紧要 when you're closing .不过,为了安全起见,请检查您最新的操作系统文档:-)

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

关于c++关闭用mmap读取的open()文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55344174/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com