私はNIX環境での高度なプログラミングを読んだ番目 章。 6つのexec関数すべてを読んで理解しました。
私が気づくのは、すべてのexec関数で:
main()
で取得するargv [0]です。これはファイル名自体です。したがって、ここでは関数でファイル名を2回渡す必要があります。
それには何らかの理由がありますか(最初の引数からパス名からファイル名を取得できないなど)?
したがって、ここでは関数でファイル名を2回渡す必要があります。
それらは、それらのoneが_argv[0]
_値として使用されていることを確認することで気づくのとまったく同じではありません。これは、実行可能ファイルのベース名と同じである必要はありません。多くの/ほとんどのものがそれを無視し、あなたが望むものをそこに置くことができます。
1つ目は、実行可能ファイルへの実際のパスです。これには、明らかに必要があります。 2番目のものは、それを呼び出すために使用された名前としてプロセスに渡されますが、例えば:
_execl("/bin/ls", "banana", "-l", NULL);
_
_/bin/ls
_が正しいパスであると仮定して、正常に動作します。
ただし、一部のアプリケーションは_argv[0]
_を使用します。通常、これらは_$PATH
_に1つ以上のシンボリックリンクがあります。これは圧縮ユーティリティでは一般的です(代わりにシェルラッパーを使用する場合があります)。 xz
がインストールされている場合、stat $(which xzcat)
はそれがxz
へのリンクであることを示し、_man xzcat
_は_man xz
_と同じで、「xzcatはxz --decompress --stdout "と同等です。 xzがどのように呼び出されたかを知る方法は、_argv[0]
_をチェックして同等のものにすることです。
_execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);
_
ファイル名を2回渡す必要はありません。
1つ目は、実際に実行されるファイルです。
2番目の引数は、argv[0]
プロセスの名前、つまり、プロセスがその名前として何を表示するか。例えば。シェルからls
を実行する場合、最初の引数は/bin/ls
、2番目はls
です。
特定のファイルを実行し、2番目の引数を介して別のファイルを呼び出すことができます。プログラムはその名前をチェックし、名前に応じて異なる動作をすることができます。これはハードリンク(またはシンボリックリンク)を介して行うこともできますが、これにより柔軟性が高まります。
重要なのは、_argv[0]
_は(NULL
を含めて)何にでも設定できるということです。 慣例により、_argv[0]
_は、実行可能ファイルが開始されたときのパスに設定されます(execve()
を実行するときにシェルプロセスによって)。
_./foo
_と_dir/bar
_が同じ実行可能ファイルへの2つの異なるリンク(ハードまたはシンボリック)である場合、2つのパスを使用してシェルからプログラムを起動すると、_argv[0]
_が_./foo
_に設定されます。および_dir/bar
_、それぞれ。
_argv[0]
_がNULL
になる可能性があるという事実は見過ごされがちです。次のコードは、たとえばNULL
_argv[0]
_の場合にクラッシュする可能性があります(ただし、glibcは_argv[0]
_の代わりに<null>のように出力します)。
_if (argc != 3) {
fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
exit(EXIT_FAILURE);
}
_
Linuxの代替手段は、そのような場合に_/proc/self/exe
_を使用することです。