it-swarm.com.de

Wie finde ich den Speicherort der ausführbaren Datei in C?

Gibt es in C/C++ eine Möglichkeit, die Position (den vollständigen Pfad) des aktuell ausgeführten Programms zu ermitteln?

(Das Problem mit argv[0] ist, dass es nicht den vollständigen Pfad gibt.)

140
eran

Zusammenfassen:

  • Unter Unixen mit /proc Ist es sehr einfach und zuverlässig:

    • readlink("/proc/self/exe", buf, bufsize) (Linux)

    • readlink("/proc/curproc/file", buf, bufsize) (FreeBSD)

    • readlink("/proc/self/path/a.out", buf, bufsize) (Solaris)

  • Unter Unixen ohne /proc (D. H. Wenn oben nicht funktioniert):

    • Wenn argv [0] mit "/" (absoluter Pfad) beginnt, ist dies der Pfad.

    • Ansonsten, wenn argv [0] "/" (relativer Pfad) enthält, hänge es an cwd an (vorausgesetzt, es wurde noch nicht geändert).

    • Anderenfalls durchsuchen Sie die Verzeichnisse in $PATH Nach der ausführbaren Datei argv[0].

    Anschließend kann es sinnvoll sein, zu prüfen, ob die ausführbare Datei tatsächlich kein Symlink ist. Wenn dies der Fall ist, wird es relativ zum Symlink-Verzeichnis aufgelöst.

    Dieser Schritt ist in/proc nicht erforderlich (zumindest für Linux). Dort zeigt der proc-Symlink direkt auf die ausführbare Datei.

    Beachten Sie, dass es Sache des aufrufenden Prozesses ist, argv[0] Richtig einzustellen. Es ist jedoch in den meisten Fällen richtig, dass der aufrufende Prozess nicht als vertrauenswürdig eingestuft werden kann (z. B. die ausführbare Datei setuid).

  • Unter Windows: GetModuleFileName(NULL, buf, bufsize) verwenden

188
lispmachine

Verwenden Sie die Funktion GetModuleFileName () , wenn Sie Windows verwenden.

21
Shino C G

Bitte beachten Sie, dass die folgenden Kommentare nur für Unix gelten.

Die pedantische Antwort auf diese Frage ist, dass es keinen allgemeinen Weg gibt, um diese Frage in allen Fällen richtig zu beantworten. Wie Sie herausgefunden haben, kann argv [0] vom übergeordneten Prozess auf einen beliebigen Wert gesetzt werden und muss daher keinerlei Beziehung zum tatsächlichen Namen des Programms oder seiner Position im Dateisystem haben.

Die folgende Heuristik funktioniert jedoch häufig:

  1. Wenn argv [0] ein absoluter Pfad ist, wird angenommen, dass dies der vollständige Pfad zur ausführbaren Datei ist.
  2. Wenn argv [0] ein relativer Pfad ist, enthält es ein /, bestimme das aktuelle Arbeitsverzeichnis mit getcwd () und hänge dann argv [0] an.
  3. Wenn argv [0] ein einfaches Wort ist, suchen Sie in $ PATH nach argv [0] und hängen Sie argv [0] an das Verzeichnis an, in dem Sie es finden.

Beachten Sie, dass all dies durch den Prozess umgangen werden kann, der das betreffende Programm aufgerufen hat. Schließlich können Sie linuxspezifische Techniken verwenden, wie sie in emg-2 erwähnt werden. Es gibt wahrscheinlich äquivalente Techniken für andere Betriebssysteme.

Selbst wenn Sie in den obigen Schritten einen gültigen Pfadnamen angeben, ist der tatsächlich gewünschte Pfadname möglicherweise noch nicht vorhanden (da ich vermute, dass Sie tatsächlich irgendwo eine Konfigurationsdatei finden möchten). Das Vorhandensein von harten Links bedeutet, dass Sie die folgende Situation haben können:

-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo     # create a hard link to foo
$ /some/where/else/foo

Nun wird der obige Ansatz (einschließlich, ich vermute,/proc/$ pid/exe) /some/where/else/foo als realer Pfad zum Programm. Und in der Tat ist es ein echter Weg zum Programm, nur nicht der, den Sie wollten. Beachten Sie, dass dieses Problem bei symbolischen Verknüpfungen nicht auftritt, die in der Praxis viel häufiger sind als harte Verknüpfungen.

Obwohl dieser Ansatz im Prinzip unzuverlässig ist, funktioniert er in der Praxis für die meisten Zwecke gut genug.

17
Dale Hagglund

Eigentlich keine Antwort, sondern nur eine Notiz, die man sich merken sollte.

Wie wir sehen konnten, ist das Problem, den Ort zu finden, an dem die ausführbare Datei ausgeführt wird, unter Linux und Unix recht schwierig und plattformspezifisch. Man sollte zweimal überlegen, bevor man das tut.

Wenn Sie Ihren ausführbaren Speicherort zum Ermitteln einiger Konfigurations- oder Ressourcendateien benötigen, sollten Sie möglicherweise die Unix-Methode zum Platzieren von Dateien im System befolgen: put configs to /etc oder /usr/local/etc oder im Home-Verzeichnis des aktuellen Benutzers und /usr/share ist ein guter Ort, um Ihre Ressourcendateien abzulegen.

10
Michael

In vielen POSIX-Systemen können Sie einen Simlink überprüfen, der sich unter/proc/PID/exe befindet. Einige Beispiele:

# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond
6
anon

Denken Sie daran, dass auf Unix-Systemen die Binärdatei möglicherweise entfernt wurde, seit sie gestartet wurde. Es ist vollkommen legal und sicher unter Unix. Zuletzt habe ich überprüft, dass Windows das Entfernen einer laufenden Binärdatei nicht zulässt.

/ proc/self/exe wird weiterhin lesbar sein, aber es wird kein funktionierender Symlink sein. Es wird ... seltsam sein.

4
Thomas

Verwenden Sie unter Mac OS X _NSGetExecutablePath .

Sehen man 3 dyld und diese Antwort auf eine ähnliche Frage.

3
Tim Ruddick

Für Linux finden Sie die /proc/self/exe wie man Dinge in einer Nizzaer Bibliothek namens binreloc bündelt, findet man die Bibliothek unter:

3
Grumbel

Ich würde

1) Verwenden Sie die Funktion basename (): http://linux.die.net/man/3/basename
2) chdir () in dieses Verzeichnis
3) Verwenden Sie getpwd (), um das aktuelle Verzeichnis abzurufen

Auf diese Weise erhalten Sie das Verzeichnis in einer ordentlichen, vollständigen Form anstelle von ./ oder ../bin/.

Vielleicht möchten Sie das aktuelle Verzeichnis speichern und wiederherstellen, wenn dies für Ihr Programm wichtig ist.

0
JCCyC