Как найти дескрипторы файлов, которые мой процесс открыл в Linux?

когда мы выполняем fork в Unix, открытые дескрипторы файлов наследуются, и если нам не нужно их использовать, мы должны их закрыть. Однако при использовании библиотек могут быть открыты дескрипторы файлов,к которым у нас нет доступа. Как проверить эти открытые дескрипторы файлов?

9 ответов


Если библиотеки открывают файлы, о которых вы не знаете, как вы знаете, что они не нужны им после вилки? Несообщаемые дескрипторы-это внутренняя деталь библиотеки, если библиотека хочет их закрыть, она зарегистрирует обработчик atfork (), чтобы закрыть их. Хождение за каким-то фрагментом кода, закрывающим его дескрипторы файлов за спиной, приведет к тонким трудным для отладки проблемам, так как библиотека неожиданно ошибется, когда попытается работать с дескриптором, который она знает, что открыла правильно, но сделала не закрывать.


в Linux вы можете проверить /proc/<pid>/fd directory-для каждого открытого fd будет файл с именем handle. Я почти уверен, что этот путь не переносной.

в качестве альтернативы вы можете использовать lsof - доступно для Linux, AIX, FreeBSD и NetBSD, согласно man lsof.


вы можете сделать из командной строки:

lsof -P -n -p _PID_

здесь PID ваш процесс pid.


как упоминалось в ответе @Louis Gerbarg, библиотеки, вероятно, ожидают, что дескрипторы файлов будут открыты на fork() (который должен быть, в конце концов, почти идентичной копией родительского процесса).

проблема большинства людей находится на exec() который часто следует за fork(). Здесь правильным решением является библиотека, которая создала дескрипторы, чтобы отметить их как close-on-exec (FD_CLOEXEC).

на библиотеках, используемых многопоточными программами, там является условием гонки между библиотекой, создающей дескриптор файла и установкой FD_CLOEXEC на нем (другой поток может fork() между обеими операциями). Чтобы решить эту проблему,O_CLOEXEC был представлен в ядре Linux.


для начала вам действительно не нужно много заботиться об открытых дескрипторах файлов, о которых вы не знаете. Если вы знаете, что не собираетесь писать им снова, закрытие их - хорошая идея и не повредит-вы просто сделали вилку() в конце концов, fds открыты дважды. Но точно так же , если вы оставите их открытыми, они не будут беспокоить вас - в конце концов, вы не знаете о них, вы, вероятно, не будете случайным образом писать им.

что касается ваших сторонних библиотек будет сделано, это немного подбрасывание в любом случае. Некоторые, вероятно, не ожидают столкнуться с ситуацией с fork () и могут случайно написать в тот же fd из двух процессов без какой-либо синхронизации. Другие, вероятно, не ожидают, что вы закроете их fds на них. Вы должны проверить. Вот почему это плохая идея, чтобы случайно открыть файловый дескриптор в библиотеке и не дать его вызывающему абоненту для управления.

все, что сказано, в духе ответа на оригинал вопрос, нет особенно хорошего способа. Вы можете позвонить dup() или dup2() в файловом дескрипторе; если он закрыт, вызов завершится с ошибкой EBADF. Так можно сказать:

int newfd = dup(oldfd);
if (newfd > 0)
{
    close(newfd);
    close(oldfd);
}

но в этот момент Вы так же хорошо говорите close(oldfd) в первую очередь и игнорируя любые EBADFs.

если вы все еще хотите принять ядерный вариант закрытия все, тогда вам нужно найти максимальное количество открытых файловых дескрипторов. Предполагая 1 до 65535 не лучшая идея. Прежде всего, fds начинается с 0, конечно, но также нет определенного верхнего предела. Чтобы быть портативными, в POSIX-х sysconf(_SC_OPEN_MAX) должен сказать вам, на любой нормальной системе POSIX, хотя, строго говоря, это необязательно. Если вы чувствуете себя параноиком, проверьте возвращаемое значение для -1, хотя в этот момент вам в основном нужно вернуться к жестко закодированному значению (1024 должно быть хорошо, если вы не делаете что-то очень странное). Или, если вы не против быть специфичным для Linux, вы можете покопаться в /процесс.

не забудьте не закрывать fds 0, 1 и 2 - это может действительно запутать вещи.


Я согласен с тем, что другие люди говорили о том, что закрытие случайных файлов опасно. Вы можете в конечном итоге подать некоторые довольно интересные отчеты об ошибках для всех ваших сторонних инструментов.

Что сказал, Если вы знаю вам не нужно, чтобы эти файлы были открыты, вы всегда можете пройти через все допустимые дескрипторы файлов (от 1 до 65535, IIRC) и закрыть все, что вы не узнаете.


разумные библиотеки всегда будут иметь функции, которые освобождают любые ресурсы (например. дескрипторы файлов) они выделили.


просто ссылка, но это кажется полезным:сколько открытых файлов? at netadmintools.com - ... Кажется, что он использует /proc-исследования, чтобы узнать об открытых файлах процесса, не уверен, что это единственный способ или есть API. Разбор файлов для этого типа информации может быть немного ... грязный. Кроме того, /proc также может быть устаревшим, что-то проверить.


разве это не проблема дизайна ? Возможно ли, чтобы ваш процесс развил перед инициализацией библиотек, которые открывают эти файлы ?