有没有一种简单的方法来获取 c++ 程序打开的文件数。
我想用我的代码来做,最好是用 C++。
我发现这篇博客文章使用循环遍历所有可用的文件描述符并测试结果,fstat
但我想知道是否有更简单的方法可以做到这一点。
编辑
除了保持打开文件的数量之外,似乎没有其他解决方案。感谢大家的帮助。
凯文
由于文件是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;
}
}
(我没有编译这段代码,它是为了展示这个概念,它可能有小错误,但我认为这个概念会成立——只要你的代码,而不是一些第三方库泄漏)
如果您在 linux 下,此信息可在/proc/you_pid/fd
.
然后lstat
在每个文件描述符上使用,以仅保留常规文件。
如果您正确封装它,添加引用计数器或记录到它并将它们打印到控制台应该很简单。
调试它的一种方法是用您自己的实现覆盖打开的调用,然后从那里调用真实的东西。然后你也可以登录,看看你是否丢失了文件描述符。你如何打开文件?使用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;
}
有一个很好的做法是在尽可能小的文件范围内打开文件,打开转储你想要的所有信息,或者缓冲到fd,然后关闭。
所以这意味着通常情况下,我们将有 3 fd std in/out/err,以及所有打开的文件。
如果您保持打开文件,最好手动跟踪打开的文件。
放一个全局 fdCounter 变量,文件打开成功后递增,关闭后递减
以我的经验,当您需要计算文件描述符的数量时,您不知道它们是在哪里打开的,是由哪个子模块或库打开的。因此,包装打开/关闭不是一个可行的策略。蛮力计数似乎是唯一的方法。
包含 orig 博客文章的域不再在 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;
}