C++ 程序中打开文件的数量

问题描述 投票:0回答:6

有没有一种简单的方法来获取c++程序打开的文件数。

我想从我的代码中做到这一点,最好是用 C++。

我发现这篇博客文章使用循环遍历所有可用的文件描述符并测试

fstat
的结果,但我想知道是否有更简单的方法可以做到这一点。

c++ file fopen
6个回答
3
投票

这是一个合理的问题:我在单元测试中计算打开的文件描述符以验证没有泄漏。在 Linux 系统上,每个打开的文件描述符在

/proc/self/fd
中都有一个条目,因此您只需对它们进行计数即可。在 c++17 中,它看起来像这样:

long file_descriptor_count() {
  return std::distance(std::filesystem::directory_iterator("/proc/self/fd"), std::filesystem::iterator{});
}

2
投票

由于文件是

FILE *
,我们可以这样做:

在到处都包含的头文件中:

#define fopen(x, y) debug_fopen(x, y, __FILE__, __LINE__)
#define fclose(x)   debug_fclose(x)

在“debugfile.cpp”中(显然不能使用上面的

#define

struct FileInfo
{
   FileInfo(const char *nm, const char fl, int ln) :  
      name(nm), file(fl), line(ln) {}

   std::string name;
   const char *file;
   int line;
};

std::map<FILE*, FileInfo> filemap;

FILE *debug_fopen(const char *fname, const char *mode, const char *file, int line)
{
   FILE *f = fopen(fname, mode);
   if (f)
   {
      FileInfo inf(fname, file, line);
      filemap[f] = inf;
   }
}

int debug_fclose(FILE *f)
{
   int res = fclose(f);
   filemap.erase(f);
   return res;
}

// Called at some points. 
void debug_list_openfiles()
{
   for( i : filemap )
   {
       cerr << "File" << (void *) i.first << " opened as " << i.second.name 
            << " at " <<  i.second.file << ":" << i.second.line << endl;
   }
}

(我还没有编译这段代码,它的目的是展示这个概念,它可能有小错误,但我认为这个概念会成立 - 只要你的代码,而不是某些第三方库泄漏)


0
投票

如果您使用的是 Linux,可以在

/proc/you_pid/fd
下找到此信息。

然后在每个文件描述符上使用

lstat
仅保留常规文件。


0
投票

如果正确封装它,向其添加引用计数器或日志记录并将其打印到控制台应该很简单。

调试它的一种方法是用您自己的实现覆盖开放调用,然后从那里调用真实的东西。然后您还可以进行一些日志记录,以查看是否丢失了文件描述符。你如何打开这些文件?使用

open()
还是您正在使用
fopen()

也许是这样的:

#include <fstream>
#include <iostream>
#include <stdlib.h>

#include <fcntl.h>

inline int log_open(char *p, int flags, int mode)
{
    int fd = ::open(p, flags, mode);
    std::cout << "OPEN: " << fd << std::endl;
    return fd;
}

inline int log_close(int fd)
{
    int rc = ::close(fd);
    std::cout << "CLOSE: " << fd << std::endl;
    return rc;
}

#define open(p, f, m)    log_open(p, f, m)
#define close(fd)   log_close(fd)

int main(int argc, char *argv[])
{
    int fd = open("tmp.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);

    std::cout << "FD: " <<  fd << std::endl;

    if(fd != -1)
        close(fd);

    return 0;
}

0
投票

根据我的经验,当您需要计算文件描述符的数量时,您不知道它们是在哪里打开的,由什么子模块或库打开。因此,环绕开/关并不是一个可行的策略。 暴力计数似乎是唯一的方法。

原始博客文章所在的域名不再在 DNS 中解析。我从 Find current number of open filehandle ( NOT lsof )

复制了两个建议
int j, n = 0;

// count open file descriptors
for (j = 0;  j < FDMAX;  ++j)     // FDMAX should be retrieved from process limits,
                                  // but a constant value of >=4K should be
                                  // adequate for most systems
{
    int fd = dup (j);
    if (fd < 0)
        continue;
    ++n;
    close (fd);
}
printf ("%d file descriptors open\n", n);

还有这个:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

int main (void)
{
   DIR *dp;
   struct dirent *ep;

   dp = opendir ("/proc/MYPID/fd/");
   if (dp != NULL)
   {
       while (ep = readdir (dp))
           puts (ep->d_name);
       (void) closedir (dp);
   }
   else
       perror ("Couldn't open the directory");

   return 0;
}

0
投票

有一个好的做法是打开的文件范围尽可能小,打开转储所有你想要的信息,或者缓冲到

fd
,然后关闭。

所以,这意味着通常情况下,我们将有 3 个

fd
,即
std
in
/
out
/
err
,以及所有打开的文件。

如果您保持文件打开状态,则最好手动跟踪打开的文件。

放置一个全局

fdCounter
变量,成功打开文件后递增,关闭后递减。

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