Как найти дескрипторы файлов, которые мой процесс открыл в Linux? - PullRequest
11 голосов
/ 06 ноября 2008

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

Ответы [ 9 ]

16 голосов
/ 06 ноября 2008

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

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

14 голосов
/ 06 ноября 2008

Вы можете сделать из оболочки:

lsof -P -n -p _PID_

Где PID - ваш процессный пид.

14 голосов
/ 06 ноября 2008

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

5 голосов
/ 06 ноября 2008

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

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

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

2 голосов
/ 06 ноября 2008

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

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

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

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

но в этот момент вы точно так же можете сказать close(oldfd) и игнорировать все EBADF.

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

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

1 голос
/ 06 ноября 2008

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

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

0 голосов
/ 06 ноября 2008

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

0 голосов
/ 06 ноября 2008

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

0 голосов
/ 06 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...