実際の答えではありませんが、覚えておくべきメモです。
ご覧のとおり、実行中の実行可能ファイルの場所を見つける問題は、Linux と Unix では非常にトリッキーで、プラットフォーム固有です。そうする前によく考えるべきです。
構成ファイルまたはリソース ファイルを検出するために実行可能な場所が必要な場合は、システムにファイルを配置する Unix の方法に従う必要があります:put configs to /etc
または /usr/local/etc
または現在のユーザーのホーム ディレクトリ、および /usr/share
リソース ファイルを置くのに適した場所です。
Windows を使用している場合は、GetModuleFileName() 関数を使用してください。
以下のコメントは UNIX 専用であることに注意してください。
この質問に対する衒学的な答えは、一般は存在しないということです。 すべてのケースでこの質問に正しく答える方法。お気づきのように、argv[0] は親プロセスによって任意の値に設定できるため、プログラムの実際の名前やファイル システム内の場所とはまったく関係がありません。
ただし、多くの場合、次のヒューリスティックが機能します:
<オール>/
が含まれている場合 、getcwd() で現在の作業ディレクトリを特定し、それに argv[0] を追加します。これらはすべて、問題のプログラムを呼び出したプロセスによって回避できることに注意してください。最後に、emg-2 で言及されているような Linux 固有の手法を使用できます。おそらく、他のオペレーティング システムにも同等の手法があります。
上記の手順で有効なパス名が得られたとしても、実際に必要なパス名をまだ持っていない可能性があります (実際にやりたいことは、どこかで構成ファイルを見つけることだと思うからです)。ハード リンクが存在するということは、次のような状況が発生する可能性があることを意味します:
-- 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
さて、上記のアプローチ (おそらく /proc/$pid/exe を含む) は /some/where/else/foo
を与えるでしょう。 プログラムへの実際のパスとして。実際、それは a です あなたが望んでいたものではなく、プログラムへの実際のパス。この問題は、実際にはハード リンクよりもはるかに一般的なシンボリック リンクでは発生しないことに注意してください。
このアプローチは原則として信頼できないという事実にもかかわらず、実際にはほとんどの目的に対して十分に機能します。
要約すると:
-
/proc
の Unix の場合 本当にまっすぐで現実的な方法は:-
readlink("/proc/self/exe", buf, bufsize)
(Linux) -
readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD) -
readlink("/proc/self/path/a.out", buf, bufsize)
(Solaris)
-
-
/proc
のない Unix の場合 (つまり、上記が失敗した場合):-
argv[0] が "/" (絶対パス) で始まる場合、これがパスです。
-
それ以外の場合、argv[0] に "/" (相対パス) が含まれている場合は、それを cwd に追加します (まだ変更されていないと仮定します)。
-
それ以外の場合は、
$PATH
のディレクトリを検索します 実行可能なargv[0]
の場合 .
その後、実行可能ファイルが実際にシンボリック リンクではないかどうかを確認するのが妥当な場合があります。シンボリック リンク ディレクトリに対して相対的に解決します。
/proc メソッドでは、この手順は必要ありません (少なくとも Linux の場合)。そこでは、proc シンボリック リンクが実行可能ファイルを直接指しています。
argv[0]
を設定するのは呼び出しプロセス次第であることに注意してください。 ほとんどの場合は正しいですが、呼び出しプロセスが信頼できない場合があります (例:setuid 実行可能ファイル)。 -
-
Windows の場合:
GetModuleFileName(NULL, buf, bufsize)
を使用します