I wanted to find all fds opened for a process in linux.
Can I do it with glib library functions ?
Use the ulimit -n command to view the number of file descriptors configured for your Linux system.
You can use /proc file system or the lsof command to find all the file descriptors used by a process.
In the /proc pseudo filesystem, we can find the open file descriptors under /proc/<pid>/fd/ where <pid> is the PID of a given process. Thus, we have to determine the process identification number (PID) of a process to look at its open file descriptors.
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.
#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:
/* 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; }
You'll probably want these too, to satisfy the last printf above...
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.
#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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With