查找当前打开的文件句柄数量(不使用lsof)

7
在*NIX系统中,有没有办法查找当前正在运行的进程中有多少个打开的文件句柄?我正在寻找一个API或C语言公式,用于在所讨论的运行进程内部使用。
4个回答

6

在某些系统上(见下文),您可以在/proc/[pid]/fd中计算它们。如果不是其中之一,请参阅下面的:wallyk的答案

在c语言中,您可以列出目录并计算总数,或列出目录内容:

 #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;
 }

在Bash中,类似于以下代码:
ls -l /proc/[pid]/fd/ | wc -l

支持proc文件系统的操作系统包括但不限于:
Solaris
IRIX
Tru64 UNIX
BSD
Linux(将其扩展到非进程相关数据)
IBM AIX(基于Linux实现以提高兼容性)
QNX
Plan 9 from Bell Labs

2
这段代码不具备可移植性,例如在FreeBSD系统中无法使用/proc/文件系统。此外,这并没有回答原帖的问题。 - arne
我喜欢wallyk的答案,它更具可移植性,并且依赖于子系统提供的非常少的设施。但是,在我的情况下,我需要确保尝试计算文件句柄的机会很高; 即通过不必打开和关闭更多的文件句柄来实现。在这个意义上,chown的解决方案更好,因为它只在努力中使用了一个额外的文件句柄。 - ϹοδεMεδιϲ
2
@CodeMedic:wallyk的解决方案只需要在任何时候添加一个额外的文件处理程序,因为它在循环内部打开和关闭它。 - salva
@salva 尽管每个 fd 都必须被 dup,这可能是可以接受的,但对于像 sockets 或跨挂载打开的 fd 等情况可能会减慢速度(没有任何支持此说法的依据,只是似乎有可能)。该方法还需要进行 3.9k 次额外的循环运行(无论如何都可以忽略不计,因为它们只是在 dup 失败时继续执行)。但对于非 /proc 文件系统,它似乎是最好的选择。 - chown

6

一个想法是在任何*nix系统上都可以使用的:

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);

残酷但非常有趣的方法。它不区分“真实”文件和终端、套接字等其他字符设备。 - arne
4
@arne:OP并没有要求区分。只需要统计打开文件句柄的总数即可。 - wallyk
1
这绝对是真的,但万一他只是忘了,我提醒了他。 - arne
我喜欢它的简洁性;但是对于我的目的,我更喜欢chown的解决方案。请查看我的评论以了解原因。 - ϹοδεMεδιϲ
不必使用复制(duping)(它使用另一个fd),你可以调用fstat并检查EBADF。 - William Pursell

1

OpenSSH 实现了一个 closefrom 函数,它执行的操作与 wallyk 和 chown 已经提出的两种方法非常相似,而且 OpenSSH 在 Unix/Linux/BSD/Cygwin 系统之间非常易于移植。


0

没有一种便携式的方法可以获取打开描述符的数量(无论类型如何),除非您自己跟踪它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接