我正在使用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
答案 0 :(得分:0)
您可以想象,保持文件打开会消耗资源。因此,在任何情况下,系统上打开文件描述符的数量都存在实际限制。这就是为什么强烈建议您关闭不再需要的文件的原因。
确切的限制取决于操作系统和配置。如果您想了解更多,这种问题已经有很多答案了。
很明显,您用mmap()
打开了一个文件。如此反复地循环执行,可能会早晚达到致命文件描述限制,这是您可能会遇到的危险。
尝试关闭文件的想法还不错。问题是它不起作用。在POSIX documentation中指定:
mmap()
函数为关联的文件添加了额外的引用 带有文件描述符fildes的文件,以后不会删除 该文件描述符上的close()
。该引用在以下位置被删除 不再有文件映射。
为什么?因为mmap()
以特殊方式将文件链接到系统中的virtual memory management。只要使用文件分配的地址范围,就需要该文件。
那么如何删除这些映射?答案是使用munmap()
:
函数
munmap()
删除了整个页面的所有映射 包含进程地址空间的任何部分,从 addr并继续len个字节。
当然,close()
是您不再需要的文件描述符。谨慎的方法是在munmap()
之后关闭,但原则上,至少在符合POSIX的系统上,when you're closing无关紧要。不过,为了安全起见,请查看最新的OS文档:-)
*注意: file mapping在Windows上也可用;如果存在剩余映射,则documentation about closing the handles可能会导致潜在的内存泄漏。这就是为什么我建议您在结束时保持谨慎。 *