Linuxでプロセス用に開かれたすべてのfdsを見つけたかったのです。
Glibライブラリ関数でそれを行うことはできますか?
Linuxを使用しているので、(ほぼ確実に)/proc
ファイルシステムがマウントされています。つまり、最も簡単な方法は、/proc/self/fd
の内容のリストを取得することです。そこにある各ファイルは、FDにちなんで名付けられています。 (もちろん、リストを行うにはg_dir_open
、g_dir_read_name
およびg_dir_close
を使用してください。)
それ以外の場合、情報を取得するのは少し厄介です(たとえば、役立つPOSIX APIはありません。これは、標準化されていない領域です)。
ここに私が使用していたいくつかのコードがありますが、/ proc/self(thx 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;
}
ファイルハンドルのリークに関する非常に悪い問題を1回経験しましたが、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 isn’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;
}
上記の最後の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は通常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;
}
これらすべてを1つのファイルにまとめると(私が確認したところ、これを行いました)、次のような出力を生成して、宣伝どおりに機能することを確認できます。
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
私はあなたが持っているすべての質問に答えることを願っています。疑問に思った場合は、私は実際にOPが尋ねた質問への回答を探してここに来ました。楽しい。
Pidを介してプロセスを識別できる場合は、簡単に行うことができます
ls -l /proc/<pid>/fd | wc - l
Cではすべてをパイプして出力を再利用するか、上記のディレクトリで自分でファイルを数えることができます(countメソッド、たとえばここでは Cを使用してディレクトリ内のファイル数を数える )
時々C++がオプションである、Boost :: filesystemを使用するDonalのソリューション:
#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;
}
プロセス内からプログラムでそれをどのように行うことができるかを意味する場合、通常の(やや恐ろしい場合)メソッドは、可能なすべての記述子をループするようなものを実行します(getrlimit()
を使用して_RLIMIT_NOFILE
_を読み取り、範囲)それぞれに対してfcntl(fd, F_GETFD, 0)
のようなものを呼び出し、EBADF応答をチェックして、開いていない応答を確認します。
シェルからプロセスが開いているファイルを確認したい場合は、_lsof -p <pid>
_が適切です。
fstatコマンドは、システムで実行中のすべてのプロセスとそれらの開いている記述子を一覧表示し、さらに、それがどの種類の記述子(ファイル、ソケット、パイプなど)であるかを一覧表示し、どのファイルシステムなど、記述子が読み書きしているのかについてのヒントを提供しようとしますそしてそのファイルシステムのどのiノード番号