私は読んだUNIX環境の高度なプログラミング著者:Stevens、第8章。私は6つのexec関数をすべて読んで理解します。
私が注目したことの1つは、すべてのexec関数で次のようなことです。
- 最初のパラメータはファイル名/パス名です(exec関数によって異なります)。
- 2番目のパラメータは、
main()
ファイル名自体のargv [0]です。
したがって、ここでは関数にファイル名を2回渡す必要があります。
何らかの理由があります(最初のパラメータのパス名からファイル名を取得できないなど)。
答え1
したがって、ここでは関数にファイル名を2回渡す必要があります。
彼らはあなたが観察することに気づいたものとまったく一致しません一つそのうちの1つが値として使用されますargv[0]
。これは実行可能ファイルのデフォルト名と同じである必要はありません。多くの/ほとんどのものがこれを無視するので、そこに欲しいものを入れることができます。
最初のものは明らかに必要な実行可能ファイルの実際のパスです。 2番目は、表面的には呼び出すために使用された名前でプロセスに渡されますが、たとえば次のようになります。
execl("/bin/ls", "banana", "-l", NULL);
/bin/ls
正しいパスだと仮定すると正常に動作します。
ただし、一部のアプリケーションはを使用しますargv[0]
。通常、これらのアプリケーションには$PATH
。これは圧縮ユーティリティで一般的です(代わりにシェルラッパーを使用する場合もあります)。xz
インストールした場合は、そのstat $(which xzcat)
リンクが表示され、xz
「xzcatはxz --decompress --stdoutと同じです」と説明したものと同じですman xzcat
。man xz
xz を調べて呼び出し方法を確認してargv[0]
同じにすることができます。
execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);
答え2
ファイル名を2回渡す必要はありません。
最初のものは実行される実際のファイルです。
2番目のパラメータはプロセスの名前argv[0]
、つまりプロセスの名前です。たとえば、ls
シェルで実行している場合、最初の引数は/bin/ls
で、2番目の引数はですls
。
2番目のパラメータでファイルを実行し、別の名前で呼び出すことができます。プログラムはファイル名を解決し、名前によって異なる動作をすることがあります。これはハードリンク(またはシンボリックリンク)を介して行うこともできますが、この方法を使用するとより柔軟性が得られます。
答え3
重要なのは、argv[0]
すべての値(含む)に設定できることですNULL
。慣例によると、argv[0]
実行可能ファイルが起動されると(シェルプロセスによって実行されるときexecve()
)、実行可能ファイルのパスに設定されます。
./foo
とが同じ実行可能ファイルへの2つの異なるリンク(ハードまたはシンボル)の場合、dir/bar
これら2つのパスを使用してシェルからプログラムを起動すると、それぞれとにargv[0]
設定されます。./foo
dir/bar
実際、この点を見落とすことがargv[0]
多いですNULL
。たとえば、次のコードは競合が発生する可能性がありますNULL
argv[0]
(glibcは次の内容を印刷しますが)。<空白>そしてargv[0]
):
if (argc != 3) {
fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
exit(EXIT_FAILURE);
}
Linuxのもう一つのオプションは、/proc/self/exe
このような状況のためのものです。