Когда мы выполняем fork в Unix, открытые дескрипторы файлов наследуются, и если нам не нужно их использовать, мы должны закрыть их. Однако, когда мы используем библиотеки, можно открывать дескрипторы файлов, для которых у нас нет доступа к дескриптору. Как проверить эти открытые дескрипторы файлов?
Как найти файлы, которые мой процесс открыл в Linux?
Ответ 1
Если библиотеки открывают файлы, о которых вы не знаете, откуда вы знаете, что они не нужны им после вилки? Неэкспортные дескрипторы - это внутренняя деталь библиотеки, если библиотека хочет их закрыть, она зарегистрирует обработчик atfork(), чтобы закрыть их. Прогулка позади некоторого фрагмента кода, закрывающего его дескрипторы файлов за его спиной, приведет к тонким трудностям для отладки проблем, так как библиотека неожиданно появится ошибка, когда она попытается работать с дескриптором, который он знает, что он открыт правильно, но не закрылся.
Ответ 2
В Linux вы можете проверить каталог /proc/<pid>/fd
- для каждого открытого fd будет файл, названный как handle. Я почти уверен, что этот способ не переносится.
В качестве альтернативы вы можете использовать lsof
- доступный для Linux, AIX, FreeBSD и NetBSD в соответствии с man lsof
.
Ответ 3
Вы можете сделать из оболочки:
lsof -P -n -p _PID_
Где PID - ваш процесс pid.
Ответ 4
Как упоминалось в ответе @Louis Gerbarg, библиотеки, вероятно, ожидают, что дескрипторы файлов будут открываться на fork()
(который, как предполагается, будет, в конечном счете, почти идентичной копией родительского процесса).
Проблема большинства людей связана с exec()
, которая часто следует за fork()
. Здесь правильное решение для библиотеки, которая создала дескрипторы, чтобы пометить их как close-on-exec (FD_CLOEXEC
).
В библиотеках, используемых многопоточными программами, существует условие гонки между библиотекой, создающей дескриптор файла, и установкой FD_CLOEXEC
на нем (другой поток может fork()
между обеими операциями). Чтобы устранить эту проблему, O_CLOEXEC
был представлен в ядре Linux.
Ответ 5
Начнем с того, что вам действительно не нужно заботиться о дескрипторах открытых файлов, о которых вы не знаете. Если вы знаете, что не собираетесь писать им снова, закрытие их - хорошая идея, и это не повредит - вы просто сделали fork() в конце концов, fds открываются дважды. Но также, если вы оставите их открытыми, они вас тоже не будут беспокоить - ведь вы не знаете о них, вы, по-видимому, не будете случайно писать им.
Что касается ваших сторонних библиотек, это немного похоже на то, что нужно. Некоторые, вероятно, не ожидают столкнуться с ситуацией с fork() и могут случайно оказаться на одном и том же fd из двух процессов без какой-либо синхронизации. Другие, вероятно, не ожидают, что вы закроете их. Вы должны будете проверить. Вот почему это плохая идея случайным образом открыть файловый дескриптор в библиотеке и не дать его вызывающему управляющему.
Все, что сказало, в духе ответа на исходный вопрос, нет особо хорошего пути. Вы можете вызвать dup()
или dup2()
в дескрипторе файла; если он закрыт, вызов завершится с EBADF
. Поэтому вы можете сказать:
int newfd = dup(oldfd);
if (newfd > 0)
{
close(newfd);
close(oldfd);
}
но в этот момент вы так же хорошо говорите close(oldfd)
и игнорируете любые EBADF.
Предполагая, что вы все еще хотите использовать ядерную опцию для закрытия всего, вам необходимо найти максимальное количество дескрипторов открытых файлов. Предполагая, что от 1 до 65535 это не очень хорошая идея. Прежде всего, fds начинаются с 0, конечно, но также нет определенного верхнего предела. Чтобы быть портативным, POSIX sysconf(_SC_OPEN_MAX)
должен сказать вам, на любой разумной системе POSIX, хотя, строго говоря, это необязательно. Если вы чувствуете себя параноиком, проверьте возвращаемое значение на -1, хотя в этот момент вам в большинстве случаев приходится возвращаться к жестко запрограммированному значению (1024 должно быть хорошо, если вы не делаете что-то чрезвычайно странное). Или, если вы в порядке с Linux-специфическими, вы можете копаться в /proc.
Не забудьте не закрывать fds 0, 1 и 2, что может действительно путать вещи.
Ответ 6
Я согласен с тем, что говорили другие люди о том, что опасные случайные файлы. В конце концов вы можете подать некоторые интересные интересные отчеты об ошибках для всех ваших сторонних инструментов.
Тем не менее, если вы знаете, что эти файлы не будут открыты, вы всегда сможете пройти через все допустимые дескрипторы файлов (от 1 до 65535, IIRC) и закрыть все, что вы не узнаете.
Ответ 7
Разумные библиотеки всегда будут иметь функции, которые освобождают любые ресурсы (например, дескрипторы файлов), которые они выделили.
Ответ 8
Просто ссылка, но она кажется полезной: Сколько открытых файлов? на netadmintools.com. Кажется, что они используют /proc для изучения открытых файлов процесса, не уверены, что это единственный способ или есть API. Разбор файлов для этого типа информации может быть немного... грязным. Кроме того, /proc может быть устаревшим тоже, что-то проверить.
Ответ 9
Разве это не проблема дизайна? Возможно ли, чтобы ваш процесс зависел до инициализации библиотек, открывающих эти файлы?