Je voulais trouver tous les fds ouverts pour un processus sous Linux.
Puis-je le faire avec les fonctions de la bibliothèque glib?
Puisque vous êtes sous Linux, vous avez (presque certainement) le /proc
système de fichiers monté. Cela signifie que la méthode la plus simple sera d'obtenir une liste du contenu de /proc/self/fd
; chaque fichier est nommé d'après un FD. (Utilisation g_dir_open
, g_dir_read_name
et g_dir_close
pour faire la liste, bien sûr.)
Sinon, obtenir les informations est modérément délicat (il n'y a pas d'API POSIX utile par exemple; c'est un domaine qui n'a pas été standardisé).
Voici du code que j'utilisais, je ne connaissais pas/proc/self (thx Donal!), Mais cette façon est probablement plus générique de toute façon. J'ai inclus les inclus requis pour toutes les fonctions en haut.
#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;
}
J'ai rencontré une fois un très mauvais problème avec des fuites de descripteurs de fichiers, et il s'avère que j'ai en fait codé la solution suggérée par 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;
}
Vous les voudrez probablement aussi, pour satisfaire le dernier printf ci-dessus ...
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 est généralement 1024, et le nombre maximal de fichiers par processus est généralement 1024. Si vous voulez être sûr, vous pouvez le remplacer par un appel à cette fonction, comme décrit par 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;
}
Si vous mettez tout cela ensemble dans un seul fichier (ce que j'ai fait, juste pour le vérifier), vous pouvez produire une sortie similaire à celle-ci pour confirmer que cela fonctionne comme annoncé:
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
J'espère que cela répond à toutes vos questions, et au cas où vous vous poseriez la question, je suis effectivement venu ici chercher la réponse à la question posée par le PO, et en lisant la réponse, rappelez-vous que j'avais déjà écrit le code il y a des années. Prendre plaisir.
Si vous pouvez identifier le processus via pid, vous pouvez simplement le faire
ls -l /proc/<pid>/fd | wc - l
En C, vous pouvez tout diriger et réutiliser la sortie ou vous pouvez compter les fichiers par vous-même dans le répertoire mentionné ci-dessus (méthode de comptage, par exemple ici Compter le nombre de fichiers dans un répertoire en utilisant C )
Parfois, C++ est une option, la solution de Donal utilisant 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;
}
Si vous voulez dire comment pouvez-vous le faire par programme à partir du processus, la méthode normale (si légèrement horrible) consiste à faire une boucle sur tous les descripteurs possibles (utilisez getrlimit()
pour lire RLIMIT_NOFILE
À trouver la plage) appeler quelque chose comme fcntl(fd, F_GETFD, 0)
sur chacun et vérifier les réponses EBADF pour voir lesquelles ne sont pas ouvertes.
Si vous voulez savoir à partir du shell quels fichiers un processus a ouverts, alors lsof -p <pid>
Est ce que vous voulez.
la commande fstat répertorie tous les processus en cours d'exécution du système et leurs descripteurs ouverts.En outre, elle répertorie de quel type de descripteur il s'agit (fichier, socket, pipe, etc.) et essaie de donner une indication de ce que le descripteur lit ou écrit, par exemple sur quel système de fichiers et quel numéro d'inode sur ce système de fichiers