Linux check file descriptors

Finding open file descriptors for a process linux ( C code )?

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 #include #include #include #include #include #include #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 #include rlim_t get_rlimit_files()

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.

Читайте также:  Лучшие графические редакторы линукс

Источник

Linux Kernel — Check if a file descriptor is taken

In linux kernel programming, is there a way to check if a particular file descriptor is in use for a given process or if it’s available?

3 Answers 3

struct files_struct * files = task->files; struct fdtable *fdt; spin_lock(&files->file_lock); fdt = files_fdtable(files); if (test_bit(fd, fdt->open_fds->fds_bits)) < /* fd is in use */ >spin_unlock(&files->file_lock); 

However, the information is potentially out of date as soon as you unlock the files struct, so the real question is what you’re going to do with it?

Assuming you are in the kernel and have a process context in struct task_struct* proc and you only want to check that the given fd corresponds to an open file in that process and not actually use the file somehow:

int is_valid_fd_for_process(int fd, struct task_struct* proc) < int exists; rcu_read_lock(); exists = (NULL != fcheck_files(proc->files, fd)); rcu_read_unlock(); return exists; > 

In case you actually want to use the file struct that this fd addresses somehow or store it for later you should aquire a reference for it. See the code for fget which does that for the current process and adapt it for any process.

If you’re really programming in the Linux kernel then you’d look at the files_struct attached to the task_struct of the process you’re interested in.

But what I think you mean is that you’re writing a userspace program to run on Linux, using the kernel API. In which case it’s a little harder.

There isn’t a direct way to do it that I’m aware of. However you should be able to do a little hack with fcntl . Basically you query the status flags for the file descriptor, and if you get an error you know (more or less) that the file descriptor is invalid — and therefore usable.

Читайте также:  Kak smenit yazik na linux

However it’s racy if you have multiple threads. Another thread could use the file descriptor after you’ve checked it. If you actually want to use that file descriptor maybe you want dup2() or F_DUPFD , but I’m not sure what you’re actually trying to do.

#include #include #include #include int main(void) < int rc, fd; for (fd = 0; fd < 8; fd++) < errno = 0; rc = fcntl(fd, F_GETFL); if (rc >= 0) printf("fd %d is open\n", fd); else if (errno == EBADF) printf("fd %d is closed\n", fd); else printf("error %d querying fd %d \n", errno, fd); > return 0; > 

Источник

How to display open file descriptors but not using lsof command

While this command displays the number of FD’s, how do you display the list of open file descriptors that the command above just counted?

You probably want to know if your ulimit is exceeded, right? I blogged about this under linuxintro.org/wiki/Is_my_ulimit_exceeded; most importantly, the ulimit is a per-process restriction that you can find under /proc/PID/limits and instead of lsof I would use ls /proc/PID/fd to list the process’ file descriptors.

2 Answers 2

There are two reasons lsof | wc -l doesn’t count file descriptors. One is that it lists things that aren’t open files, such as loaded dynamically linked libraries and current working directories; you need to filter them out. Another is that lsof takes some time to run, so can miss files that are opened or closed while it’s running; therefore the number of listed open files is approximate. Looking at /proc/sys/fs/file-nr gives you an exact value at a particular point in time.

cat /proc/sys/fs/file-nr is only useful when you need the exact figure, mainly to check for resource exhaustion. If you want to list the open files, you need to call lsof , or use some equivalent method such as trawling /proc/*/fd manually.

Hi thanks for giving a good explanation Gilles. I tried ls /proc/*/fd and got all the open fd’s at that time. Its producing an output with some color coding, I’ll just have to look at the manual.

@dimas /proc/*/fd directories contain symbolic links to the open files. For visual inspection, use ls -l . For automated treatment, use readlink to extract the link target.

Читайте также:  Linux no such file or directory path

Just use ls -l but i’ll experiment with readlink. I tried other /proc/PID/maps and other options as specified here kernel.org/doc/man-pages/online/pages/man5/proc.5.html. Thanks again for the additional info.

/proc/sys/fs/file-nr gives me 3872 (and two other numbers). How can this be the count of files I have open if ulimit -n shows me 1024?

@ThorstenStaerk All settings of setrlimit (the system call underlying the ulimit shell command) are per-process. They affect only the process that makes the call (and indirectly the processes that it later forks).

Process information is kept dynamically by the system in directories under /proc. For example the process with PID 1234 will have a directory called /proc/1234.

There are quite a bit of information in there but right now you are interested in the /proc/1234/fd subdirectory.

NOTE: You need to have root permissions to view or open files for processes that you do not own, as well as for SetUID processes.

root@johan-HP-ProBook-6560b-LG654EA-ACQ:/proc# ls -l 2443/fd total 0 lr-x------ 1 johan johan 64 Feb 27 10:26 0 -> pipe:[13637] l-wx------ 1 johan johan 64 Feb 27 10:26 1 -> /home/johan/.xsession-errors lrwx------ 1 johan johan 64 Feb 27 10:26 10 -> anon_inode:[eventfd] lrwx------ 1 johan johan 64 Feb 27 10:26 11 -> anon_inode:[eventfd] lrwx------ 1 johan johan 64 Feb 27 10:26 12 -> socket:[39495] lrwx------ 1 johan johan 64 Feb 27 10:26 13 -> anon_inode:[eventfd] lr-x------ 1 johan johan 64 Feb 27 10:26 14 -> anon_inode:inotify lrwx------ 1 johan johan 64 Feb 27 10:26 15 -> anon_inode:[eventfd] l-wx------ 1 johan johan 64 Feb 27 10:26 16 -> pipe:[37885] lr-x------ 1 johan johan 64 Feb 27 10:26 17 -> pipe:[37886] l-wx------ 1 johan johan 64 Feb 27 10:26 2 -> /home/johan/.xsession-errors l-wx------ 1 johan johan 64 Feb 27 10:26 21 -> pipe:[167984] lr-x------ 1 johan johan 64 Feb 27 10:26 22 -> pipe:[167985] l-wx------ 1 johan johan 64 Feb 27 10:26 23 -> pipe:[170009] lr-x------ 1 johan johan 64 Feb 27 10:26 24 -> pipe:[170010] lrwx------ 1 johan johan 64 Feb 27 10:26 3 -> anon_inode:[eventfd] lr-x------ 1 johan johan 64 Feb 27 10:26 4 -> pipe:[14726] lrwx------ 1 johan johan 64 Feb 27 10:26 5 -> socket:[14721] l-wx------ 1 johan johan 64 Feb 27 10:26 6 -> pipe:[14726] lrwx------ 1 johan johan 64 Feb 27 10:26 7 -> socket:[14730] lrwx------ 1 johan johan 64 Feb 27 10:26 8 -> socket:[13984] lrwx------ 1 johan johan 64 Feb 27 10:26 9 -> socket:[14767] root@johan-HP:/proc# cat 2443/fdinfo/2 pos: 1244446 flags: 0102001 

Also have a look at the rest of the files under /proc . a lot of useful information from the system resides here.

Источник

Оцените статью
Adblock
detector