¿Encontrar descriptores de archivo abiertos para un proceso de linux (código C)?

Quería encontrar todos los fds abiertos para un proceso en linux.

¿Puedo hacerlo con las funciones de la biblioteca glib?

Ya que está en Linux, (casi con seguridad) ha montado el sistema de archivos /proc . Eso significa que el método más fácil será obtener una lista de los contenidos de /proc/self/fd ; cada archivo allí se nombra después de un FD. (Utilice g_dir_open , g_dir_read_name y g_dir_close para hacer el listado, por supuesto).

Obtener la información de lo contrario es moderadamente incómodo (por ejemplo, no hay una API POSIX útil; esta es un área que no estaba estandarizada).

Aquí hay un código que solía usar, no conocía / proc / self (¡Donal!), Pero esta forma es probablemente más genérica de todos modos. He incluido los requisitos necesarios para todas las funciones en la parte superior.

 #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; } 

Pasé por un problema muy grave al filtrar los manejadores de archivos una vez, y resulta que en realidad codifiqué la solución que sugirió 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; } 

Probablemente querrás estos también, para satisfacer la última impresión de arriba ...

 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 suele ser 1024, y el máximo de archivos por proceso suele ser 1024. Si desea estar seguro, puede reemplazarlo con una llamada a esta función, como lo describe TomH.

 #include  #include  rlim_t get_rlimit_files() { struct rlimit rlim; getrlimit(RLIMIT_NOFILE, &rlim); return rlim.rlim_cur; } 

Si pones todo eso en un solo archivo (lo que hice, solo para revisarlo), puedes producir una salida similar a esta para confirmar que funciona como se anuncia:

 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 

Espero que responda a cualquier pregunta que tenga, y en caso de que se lo esté preguntando, realmente vine aquí buscando la respuesta a la pregunta que hizo el OP, y al leer la respuesta, recuerde que ya había escrito el código hace años. Disfrutar.

Si puede identificar el proceso a través de pid, simplemente puede hacer

 ls -l /proc//fd | wc - l 

En C, puede canalizar todo y reutilizar la salida o puede contar los archivos usted mismo en el directorio mencionado anteriormente (método de conteo, por ejemplo, aquí Contando el número de archivos en un directorio usando C )

A veces, C ++ es una opción, la solución de Donal que usa boost :: filesystem:

 #include  #include  #include  #include  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 te refieres a cómo puedes hacerlo programáticamente desde el proceso, entonces el método normal (aunque un poco horrible) es hacer algo como hacer un bucle sobre todos los descriptores posibles (usa getrlimit() para leer RLIMIT_NOFILE para encontrar el rango) llamando a algo como fcntl(fd, F_GETFD, 0) en cada una y verificando las respuestas de EBADF para ver cuáles no están abiertas.

Si quiere decir que quiere averiguar desde la shell qué archivos tiene abierto un proceso, entonces lo que desea es lsof -p .

El comando fstat enumera todos los procesos en ejecución del sistema y sus descriptores abiertos, además, enumera qué tipo de descriptor es (archivo, socket, tubería, etc.) e intenta dar una pista de lo que el descriptor está leyendo o escribiendo, como qué sistema de archivos y qué número de inodo en ese sistema de archivos