为进程linux(C代码)查找打开的文件描述符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6583158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding open file descriptors for a process linux ( C code )?
提问by Ashish
I wanted to find all fds opened for a process in linux.
我想在 linux 中找到为进程打开的所有 fds。
Can I do it with glib library functions ?
我可以用 glib 库函数来做吗?
采纳答案by Donal Fellows
Since you're on Linux, you've (almost certainly) got the /proc
filesystem mounted. That means that the easiest method is going to be to get a list of the contents of /proc/self/fd
; each file in there is named after a FD. (Use g_dir_open
, g_dir_read_name
and g_dir_close
to do the listing, of course.)
由于您使用的是 Linux,因此您(几乎可以肯定)已经/proc
安装了文件系统。这意味着最简单的方法是获取/proc/self/fd
;的内容列表。其中的每个文件都以 FD 命名。(当然,使用g_dir_open
,g_dir_read_name
和g_dir_close
来列出。)
Getting the information otherwise is moderately awkward (there's no helpful POSIX API for example; this is an area that wasn't standardized).
以其他方式获取信息有点笨拙(例如,没有有用的 POSIX API;这是一个未标准化的领域)。
回答by fyr
If you can identify the process via pid you can simply do
如果你可以通过pid识别进程,你可以简单地做
ls -l /proc/<pid>/fd | wc - l
In C you can pipe everything and reuse either the output or you may count the files by yourself in the above mentioned directory(count method e.g. here Counting the number of files in a directory using C)
在 C 中,您可以通过管道传输所有内容并重用输出,或者您可以自己计算上述目录中的文件(计数方法,例如此处使用 C 计算目录中的文件数)
回答by TomH
If you mean how can you do it programatically from within the process then the normal (if slightly horrid) method is to do something like looping over all possible descriptors (use getrlimit()
to read RLIMIT_NOFILE
to find the range) calling something like fcntl(fd, F_GETFD, 0)
on each one and checking for EBADF responses to see which ones are not open.
如果您的意思是如何从进程内以编程方式执行此操作,那么正常(如果有点可怕)方法是执行诸如循环所有可能的描述符(用于getrlimit()
读取RLIMIT_NOFILE
以查找范围)之类的操作,fcntl(fd, F_GETFD, 0)
在每个描述符上调用类似的内容并检查EBADF 响应以查看哪些未打开。
If you mean that you want to find out from the shell what files a process has open then lsof -p <pid>
is what you want.
如果你的意思是你想从 shell 中找出一个进程打开了哪些文件,那么lsof -p <pid>
这就是你想要的。
回答by maheshgupta024
fstat command lists all running processes of the system and their open descriptors furthermore it lists what type of descriptor it is (file, socket, pipe, etc) and tries to give a hint of what the descriptor is reading or writing on such as what filesystem and what inode number on that file system
fstat 命令列出了系统中所有正在运行的进程及其打开的描述符,此外它还列出了它是什么类型的描述符(文件、套接字、管道等),并尝试提示描述符正在读取或写入的内容,例如什么文件系统以及该文件系统上的 inode 编号
回答by Orwellophile
Here's some code I used to use, I didn't know about /proc/self (thx Donal!), but this way is probably more generic anyway. I've included the required includes for all the functions at the top.
这是我曾经使用过的一些代码,我不知道 /proc/self (感谢 Donal!),但无论如何这种方式可能更通用。我已经在顶部包含了所有功能所需的包含。
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/resource.h>
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
/* implementation of Donal Fellows method */
int get_num_fds()
{
int fd_count;
char buf[64];
struct dirent *dp;
snprintf(buf, 64, "/proc/%i/fd/", getpid());
fd_count = 0;
DIR *dir = opendir(buf);
while ((dp = readdir(dir)) != NULL) {
fd_count++;
}
closedir(dir);
return fd_count;
}
I went through a very bad problem with leaking file handles once, and it turns out I actually coded the solution Tom H. suggested:
我曾经遇到过一个非常糟糕的文件句柄泄漏问题,结果证明我实际上编写了 Tom H. 建议的解决方案:
/* check whether a file-descriptor is valid */
int pth_util_fd_valid(int fd)
{
if (fd < 3 || fd >= FD_SETSIZE)
return FALSE;
if (fcntl(fd, F_GETFL) == -1 && errno == EBADF)
return FALSE;
return TRUE;
}
/* check first 1024 (usual size of FD_SESIZE) file handles */
int test_fds()
{
int i;
int fd_dup;
char errst[64];
for (i = 0; i < FD_SETSIZE; i++) {
*errst = 0;
fd_dup = dup(i);
if (fd_dup == -1) {
strcpy(errst, strerror(errno));
// EBADF oldfd isna?t an open file descriptor, or newfd is out of the allowed range for file descriptors.
// EBUSY (Linux only) This may be returned by dup2() during a race condition with open(2) and dup().
// EINTR The dup2() call was interrupted by a signal; see signal(7).
// EMFILE The process already has the maximum number of file descriptors open and tried to open a new one.
} else {
close(fd_dup);
strcpy(errst, "dup() ok");
}
printf("%4i: %5i %24s %s\n", i, fcntl(i, F_GETOWN), fd_info(i), errst);
}
return 0;
}
You'll probably want these too, to satisfy the last printf above...
你可能也想要这些,以满足上面最后一个 printf ......
char *fcntl_flags(int flags)
{
static char output[128];
*output = 0;
if (flags & O_RDONLY)
strcat(output, "O_RDONLY ");
if (flags & O_WRONLY)
strcat(output, "O_WRONLY ");
if (flags & O_RDWR)
strcat(output, "O_RDWR ");
if (flags & O_CREAT)
strcat(output, "O_CREAT ");
if (flags & O_EXCL)
strcat(output, "O_EXCL ");
if (flags & O_NOCTTY)
strcat(output, "O_NOCTTY ");
if (flags & O_TRUNC)
strcat(output, "O_TRUNC ");
if (flags & O_APPEND)
strcat(output, "O_APPEND ");
if (flags & O_NONBLOCK)
strcat(output, "O_NONBLOCK ");
if (flags & O_SYNC)
strcat(output, "O_SYNC ");
if (flags & O_ASYNC)
strcat(output, "O_ASYNC ");
return output;
}
char *fd_info(int fd)
{
if (fd < 0 || fd >= FD_SETSIZE)
return FALSE;
// if (fcntl(fd, F_GETFL) == -1 && errno == EBADF)
int rv = fcntl(fd, F_GETFL);
return (rv == -1) ? strerror(errno) : fcntl_flags(rv);
}
FD_SETSIZE is usually 1024, and the maximum files per process is usually 1024. If you want to be sure, you can replace it with a call to this function, as described by TomH.
FD_SETSIZE 通常为 1024,每个进程的最大文件数通常为 1024。如果你想确定,你可以用调用这个函数来代替它,如 TomH 所述。
#include <sys/time.h>
#include <sys/resource.h>
rlim_t get_rlimit_files()
{
struct rlimit rlim;
getrlimit(RLIMIT_NOFILE, &rlim);
return rlim.rlim_cur;
}
If you put all of that together into a single file (which I did, just to check it), you can produce an output similar to this to confirm it works as advertised:
如果您将所有这些放在一个文件中(我这样做,只是为了检查它),您可以生成与此类似的输出,以确认它如宣传的那样工作:
0: 0 O_RDWR dup() ok
1: 0 O_WRONLY dup() ok
2: 0 O_RDWR dup() ok
3: 0 O_NONBLOCK dup() ok
4: 0 O_WRONLY O_NONBLOCK dup() ok
5: -1 Bad file descriptor Bad file descriptor
6: -1 Bad file descriptor Bad file descriptor
7: -1 Bad file descriptor Bad file descriptor
8: -1 Bad file descriptor Bad file descriptor
9: -1 Bad file descriptor Bad file descriptor
I hope that answers any questions you have, and in case you were wondering, I actually came here looking for the answer to the question the OP asked, and upon reading the answered, remember I had already written the code years ago. Enjoy.
我希望能回答您的任何问题,如果您想知道,我实际上是来这里寻找 OP 提出的问题的答案,在阅读答案后,请记住我几年前已经编写了代码。享受。
回答by Janek Olszak
Sometimes C++ is an option, Donal's solution using boost::filesystem:
有时 C++ 是一种选择,Donal 的解决方案使用 boost::filesystem:
#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <unistd.h>
namespace fs = boost::filesystem;
int main()
{
std::string path = "/proc/" + std::to_string(::getpid()) + "/fd/";
unsigned count = std::distance(fs::directory_iterator(path),
fs::directory_iterator());
std::cout << "Number of opened FDs: " << count << std::endl;
}