Есть ли более быстрый способ проверить, используется ли файл?

8

Я ищу функцию командной строки или функцию c, которая сообщит мне, если файл открыт / используется чем-то.

lsofи fuserдействительно говорите об этом, но они предоставляют много другой информации, которая в некоторых случаях может занять до 300 мс (например, когда я использую этот код в MAC OS X, я использую Linux и OS X) (у меня есть окна решение, которое занимает 5 мс, поэтому я пытаюсь найти что-то в Unix, что также очень быстро, и просто возвращает истину или ложь, если файл используется)

Noitidart
источник

Ответы:

9

Если вы используете это как замок, он не будет работать , как ни lsofили fuserпредотвратить условия гонки.

Основной процесс, который lsofделает это, - это обход всех процессов, /proc/*/fsищущих дескрипторы открытых файлов. Это займет время независимо от того, что вы делаете.

Вы можете сделать это самостоятельно, но вряд ли это будет быстрее, поскольку вам нужно проверять каждый открытый процесс в системе.

Если то, что вы делаете, критично ко времени, найдите другой способ сделать это.

  • Если вы управляете файлом через программу, которую вы написали; использовать файл блокировки.
  • Если вы выполняете какую-либо команду, которая работает с файлом, посмотрите и посмотрите, какую документацию предлагает эта команда / программа, и посмотрите, не может ли она создать файл блокировки. В противном случае посмотрите, не может ли он создать файл с его PID внутри. Затем вы можете посмотреть, /proc/<PID>/fsоткрыт ли ваш файл в настоящее время или нет. Просмотр только одного дескриптора открытого файла процесса будет намного быстрее, чем отображение всех из них.
  • В противном случае, чтобы помочь вам, мне понадобится дополнительная информация о том, что вы делаете.

Вы дали больше информации в комментарии, который вы хотите определить, работает ли Firefox в данной системе. Лучший способ сделать это - найти файлы блокировки Firefox. Они хранятся в местах по умолчанию, указанных в вики Mozilla.

Например, в Linux ваша программа должна сделать следующее:

  • откройте ~/.mozilla/firefox/каталог.
  • Список всех каталогов, фильтрация по каталогам, оканчивающимся на .default. (Я думаю, что все профили заканчиваются .default, если не просто лезть в каждый каталог.)
  • В каждом каталоге выше найдите файл с именем lockили .parentlock. Если вы видите один или оба файла, Firefox открыт.

Этот алгоритм должен выполняться быстрее, чем то, что вы делаете в Windows в настоящее время.

nixeagle
источник
Отличный ответ спасибо. Можно ли как-то сказать lsof и fuser проверять папку pid, только если это firefox? Это сделало бы его пропустить все содержимое папок для папок светлячка , за исключением ( у меня есть 3 раздельных экземпляров так что означает , что он проверяет только 3 папки правильно?)
Noitidart
Файл заблокирован, но я не могу понять, как проверить, заблокирован ли он. Он успешно открывается для чтения / записи. Это так странно. Я пробовал fcntl из c, но он всегда возвращает -1 :(
Noitidart
3
@Noitidart Какую реальную проблему вы пытаетесь решить? Чтобы найти дескрипторы открытого файла любого процесса, вы должны знать его PID. Это меняется для каждого экземпляра программы. Простой способ получить это "вручную" - с ps aux firefox. Возьмите эти PID и найдите их в /proc/файловой системе.
nixeagle
Ах, спасибо, это хорошая идея ps aux firefox. Ну, моя точная ситуация такова: у меня есть путь к файлу. Он заблокирован, если запущен Firefox. Я хочу увидеть, заблокирован ли он или нет, чтобы узнать, работает ли Firefox.
Noitidart
1
@ Noitidart Я отредактировал свой комментарий, чтобы включить в него способ обнаружения Firefox по файлам блокировки. Вы можете повторить этот процесс на всех системах.
nixeagle
1

TL; DR

В одном из ваших комментариев вы заявляете:

Ну, моя точная ситуация такова: у меня есть путь к файлу. Он заблокирован, если запущен Firefox. Я хочу увидеть, заблокирован ли он или нет, чтобы узнать, работает ли Firefox.

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

Изучение состояния процесса

Более разумный способ найти PID данного процесса - использовать pgrep из пакета procps . Например:

$ pgrep -u $LOGNAME firefox
5671

Затем вы можете проверить состояние PID с помощью ps :

$ ps 5671
  PID TTY      STAT   TIME COMMAND
 5671 ?        Sl   105:47 /usr/lib/firefox/firefox

или просто получи государственные флаги без всякой хулиганы

$ ps -ho stat $(pgrep -u $LOGNAME firefox)
Sl

Одна моя система, одна строка выше, последовательно занимает всего 1,4 миллисекунды. Ваш пробег может варьироваться.

Коды состояния процесса

Раздел «КОДЫ СОСТОЯНИЯ ПРОЦЕССА» в ps (1) подробно описывает, что означают различные флаги состояния. На Ubuntu 14.04 на странице руководства написано:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output
       specifiers (header "STAT" or "S") will display to describe the state of
       a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is
                    being traced
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by
                    its parent

       For BSD formats and when the stat keyword is used, additional
       characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads
                    do)
               +    is in the foreground process group
CodeGnome
источник
1
проблема в том, что ему нужно знать, в каком сеансе находится Firefox. В Linux вы просто ищете ~/.mozilla/firefox/*/lock. Затем вы можете идентифицировать сеанс, посмотрев имя родительского каталога каждого файла блокировки. На других платформах это не работает. Наш чат рассказывает больше о том, как заставить его работать на Mac (что не очень важно для Ubuntu, но у вас это есть). Чтобы быть справедливым, он действительно должен обновить вопрос, чтобы быть более конкретным. : P
nixeagle