Gibt es eine schnellere Möglichkeit, um zu überprüfen, ob eine Datei verwendet wird?

8

Ich suche nach einer Befehlszeilenfunktion oder einer c-Funktion, die mich darüber informiert, ob eine Datei von etwas geöffnet / verwendet wird.

lsofund fusersagen Sie dies, aber sie bieten viele andere Informationen, die in einigen Situationen bis zu 300 ms dauern (z. B. wenn ich diesen Code unter MAC OS X verwende, entwickle ich für Linux und OS X) (ich habe ein Windows Lösung, die 5 ms dauert, also versuche ich, etwas in Unix zu finden, das auch sehr schnell ist und nur true oder false zurückgibt, wenn eine Datei verwendet wird.

Noitidart
quelle

Antworten:

9

Wenn Sie dies als Schloss verwenden, funktioniert es weder als lsofnoch fuserverhindert es die Rennbedingungen.

Der grundlegende Prozess lsofbesteht darin, alle Prozesse /proc/*/fsnach offenen Dateideskriptoren zu durchsuchen. Dies wird einige Zeit dauern, egal was Sie tun.

Sie können dies selbst tun, aber es ist wahrscheinlich nicht schneller, da Sie nach jedem offenen Prozess auf dem System suchen müssen.

Wenn das, was Sie tun, zeitkritisch ist, finden Sie einen anderen Weg, dies zu tun.

  • Wenn Sie die Datei über ein von Ihnen geschriebenes Programm steuern; Verwenden Sie eine Sperrdatei.
  • Wenn Sie einen Befehl ausführen, der für die Datei ausgeführt wird, überprüfen Sie, welche Dokumentation dieser Befehl / dieses Programm bietet, und prüfen Sie, ob keine Sperrdatei erstellt werden kann. Andernfalls prüfen Sie, ob keine Datei mit der darin enthaltenen PID erstellt werden kann. Dann können Sie überprüfen /proc/<PID>/fs, ob Ihre Datei gerade geöffnet ist oder nicht. Wenn Sie nur einen Prozess betrachten, sind offene Dateideskriptoren viel schneller als die Zuordnung über alle Prozesse.
  • Andernfalls benötige ich weitere Informationen darüber, was Sie tun, um Ihnen zu helfen.

Sie haben in einem Kommentar weitere Informationen angegeben, mit denen Sie feststellen möchten, ob Firefox auf einem bestimmten System ausgeführt wird. Der beste Weg, dies zu tun, besteht darin, nach den Sperrdateien von Firefox zu suchen. Diese werden an den im Mozilla-Wiki angegebenen Standardspeicherorten gespeichert .

Lassen Sie Ihr Programm unter Linux beispielsweise Folgendes ausführen:

  • Öffnen Sie das ~/.mozilla/firefox/Verzeichnis.
  • Listen Sie alle Verzeichnisse auf und filtern Sie nach Verzeichnissen, die auf enden .default. (Ich denke, alle Profile enden mit .default, wenn nicht nur in jedes Verzeichnis kriechen.)
  • Suchen Sie in jedem Verzeichnis oben nach einer Datei mit dem Namen lockoder .parentlock. Wenn Sie eine oder beide Dateien sehen, ist Firefox geöffnet.

Dieser Algorithmus sollte schneller ausgeführt werden als derzeit unter Windows.

Nixeagle
quelle
Hervorragende Antwort, danke. Gibt es eine Möglichkeit, lsof und fuser anzuweisen, den PID-Ordner nur zu überprüfen, wenn es sich um Firefox handelt? Das würde dazu führen, dass der gesamte Inhalt von Ordnern außer den Ordnern von Firefox übersprungen wird (ich habe 3 separate Instanzen, was bedeutet, dass nur 3 Ordner überprüft werden, oder?)
Noitidart
Die Datei ist gesperrt, aber ich kann nicht herausfinden, wie ich testen kann, ob sie gesperrt ist. Es wird erfolgreich zum Lesen / Schreiben geöffnet. Es ist so seltsam. Ich habe versucht, fcntl von c, aber es ist immer -1 :(
Noitidart
3
@Noitidart Was ist Ihr eigentliches Problem, das Sie lösen möchten? Um die offenen Dateideskriptoren eines Prozesses nachschlagen zu können, müssen Sie dessen PID kennen. Dies ändert sich für jede Instanz des Programms. Eine einfache Möglichkeit, es "manuell" zu erhalten, ist mit ps aux firefox. Nehmen Sie diese PIDs und suchen Sie sie im /proc/Dateisystem nach.
Nixeagle
Ah, danke, das ist eine gute Idee ps aux firefox. Nun, meine genaue Situation ist: Ich habe den Pfad zu einer Datei. Es ist gesperrt, wenn Firefox ausgeführt wird. Ich möchte sehen, ob es gesperrt ist oder nicht, ob Firefox ausgeführt wird.
Noitidart
1
@Noitidart Ich habe meinen Kommentar so bearbeitet, dass er enthält, wie Firefox anhand von Sperrdateien erkannt wird. Sie können diesen Vorgang auf allen Systemen wiederholen.
Nixeagle
1

TL; DR

In einem Ihrer Kommentare geben Sie an:

Nun, meine genaue Situation ist: Ich habe den Pfad zu einer Datei. Es ist gesperrt, wenn Firefox ausgeführt wird. Ich möchte sehen, ob es gesperrt ist oder nicht, ob Firefox ausgeführt wird.

Ihre ursprüngliche Frage zu Sperrdateien scheint weit entfernt zu sein, wenn es einfachere Möglichkeiten gibt, herauszufinden, ob Firefox für einen bestimmten Benutzer ausgeführt wird, und seinen Prozessstatus zu überprüfen.

Prozessstatus untersuchen

Ein sinnvollerer Weg, um die PID eines bestimmten Prozesses zu ermitteln, ist die Verwendung von pgrep aus dem procps- Paket. Zum Beispiel:

$ pgrep -u $LOGNAME firefox
5671

Sie können dann den Status der PID mit ps überprüfen :

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

oder holen Sie sich einfach die Staatsflaggen ohne andere Kruft:

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

Bei einem meiner Systeme dauert der oben genannte Einzeiler durchweg nur 1,4 Millisekunden. Ihr Kilometerstand kann variieren.

Prozessstatuscodes

Im Abschnitt PROCESS STATE CODES von ps (1) wird detailliert beschrieben, was die verschiedenen Statusflags bedeuten. Unter Ubuntu 14.04 heißt es auf der Manpage:

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
quelle
1
Das Problem ist, dass er wissen muss, in welcher Sitzung sich Firefox gerade befindet. Unter Linux suchen Sie einfach nach ~/.mozilla/firefox/*/lock. Sie können die Sitzung dann identifizieren, indem Sie den übergeordneten Verzeichnisnamen jeder Sperrdatei anzeigen. Auf anderen Plattformen funktioniert dies nicht. In unserem Chat geht es mehr darum, wie man es auf Macs zum Laufen bringt (was für Ubuntu irgendwie irrelevant ist, aber da haben Sie es). Um fair zu sein, sollte er die Frage wirklich aktualisieren, um genauer zu sein. : P
Nixeagle