exec関数でファイル名を2回渡す必要があるのはなぜですか?


12

StevensによるUNIX環境での高度なプログラミングの 8 章を読みました。6つのexec関数をすべて読んで理解しました。

私が気づくのは、すべてのexec関数で:

  • 最初の引数はファイル名/パス名です(exec関数によって異なります)。
  • 2番目の引数はmain()、取得するargv [0]です。これは、ファイル名自体です。

したがって、ここでは関数でファイル名を2回渡す必要があります。

それには理由がありますか(最初の引数からパス名からファイル名を取得できないなど)?

回答:


15

したがって、ここでは関数でファイル名を2回渡す必要があります。

それらの1つがargv[0]値として使用されていることを確認すると、これらはまったく同じではありません。これは、実行可能ファイルのベース名と同じである必要はありません。多くの/ほとんどのものがそれを無視し、あなたはそこに好きなものを置くことができます。

1つ目は、実行可能ファイルへの実際のパスです。これには明らかに必要があります。2番目のものは、それを呼び出すために使用された名前としてプロセスに渡されますが、例えば:

execl("/bin/ls", "banana", "-l", NULL);

正常に動作し/bin/ls、正しいパスであると推定されます。

ただし、一部のアプリケーションはを使用しargv[0]ます。通常、これらにはに1つ以上のシンボリックリンクがあり$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);

5
ああ、それで、これはbusyboxあなたがそれをどのように正しく呼ぶかに依存して、あなたがそれがどのようになりたいかを説明することができるでしょうか?
terdon

4
@terdonそれは、busyboxの単一のバイナリが非常に多くの異なるコマンドを満たす方法です。
ma

7
/bin/lsつまり、busyboxの場合、実行方法がわかりませんbanana
2015年

6

ファイル名を2回渡す必要はありません。

1つ目は、実際に実行されるファイルです。

2番目の引数はargv[0]、プロセスの名前、つまりプロセスがその名前として何を表示するかです。たとえばls、シェルから実行する場合、最初の引数は/bin/ls、2番目の引数はlsです。

特定のファイルを実行して、2番目の引数を介して別のファイルを呼び出すことができます。プログラムはその名前をチェックし、名前に応じて異なる動作をすることができます。これはハードリンク(またはシンボリックリンク)を介して行うこともできますが、これにより柔軟性が高まります。


実際、リンクはargv[0]リンク名に設定されるため、リンクは同じメソッドです。
goldilocks 2015年

最後の段落では、「特定のファイルを実行して、2番目の引数を介してそれを別の名前で呼び出すことができます。プログラムはその名前を確認し、名前に応じて「異なる」動作をすることができます。」詳しい説明を読んだり、読んだりしてください。この環境は初めてです。
munjal007 2015年

ゴルディロックスの答えの最後の部分はこれを説明しています。
wurtel 2015年

1

要点は、argv[0]何でも設定できることです(を含むNULL)。慣例ではargv[0](それがないシェルプロセスで実行可能として開始されたパスに設定されますexecve())。

場合./foodir/bar同じ実行する(ハードまたはシンボリック)は、2つの異なるリンクであり、次いで、セットする二つの経路を使用してシェルからプログラムを起動argv[0]する./foodir/bar、それぞれ、。

ありargv[0]得る事実NULLはしばしば見落とされます。NULL argv[0]たとえば、次のコードはクラッシュする可能性があります(glibcはの代わりに<null>のようなものを出力しますargv[0])。

if (argc != 3) {
    fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
    exit(EXIT_FAILURE);
}

Linuxの代替手段は/proc/self/exe、このような場合に使用することです。


どのように./fooとdir /バーの両方に[0] ARGVを設定することができます
munjal007

@ munjal007ご不明な点はごめんなさい。プログラムを2回実行することを意味しました:1回./fooと1回dir/barargv[0]これらの2つのケースでは異なります(どちらの場合も、使用したパスと同じになります)。
Ulfalizer、2015年

@ munjal007もちろん、シェルから実行することを前提としています。重要なのは、自分でプログラムargv[0]を作成するときにexec*()、何にでも設定できるということです。argv[0]プログラムを起動するために使用されたパスに設定するのはシェルの規則です(exec*()多くのプログラムargv[0]がパスを保持していることを検査して期待するため、プログラムを実行するときに同じことを行うのが賢明です)。
Ulfalizer、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.