web-dev-qa-db-ja.com

execvpはどのようにコマンドを実行しますか?

execvpを使用して、次のように簡単なコマンドを実行できることを知っています。

_char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
_

execvpを実行すると、ここで何が起こっているのかを知りたいです。マニュアルページでは、execvpはプロセスイメージのイメージを新しいイメージに置き換えます。ただし、ここでは実行可能ファイルではなくコマンドを実行しています。

具体的には、入力が特に必要なコマンドがあるとします。ネコ。 catに必要なファイル名を含むテキストファイルtext.txtがあり、stdinをファイルのファイルストリームにリダイレクトすると、execle("cat","cat",NULL)またはexecvp("cat", arg)(明らかにargが_"cat"_およびNULL)を格納する場所は、_cat /filename_のようにコンソールに出力されますか?私の直感では、ファイルを読み取る必要があり、それを解析して引数を引数に保存することができます。しかし、私は確認したい。

前もって感謝します!

21
as3rdaccount

execvp呼び出しで起こることは次のとおりです。

  1. Libc実装は、PATHで、該当する場合、実行されるファイルを検索します。すべてではないにしても、ほとんどのUNIXライクシステムのコマンドは実行可能ファイルです。そうでない場合はどうなりますか?それを試してみてください。 glibcの仕組み をご覧ください。
  2. 通常、実行可能ファイルが見つかった場合、execveが呼び出されます。 execveの一部はlibcで実装されるか、システムコール(Linuxなど)で実装されます。
  3. Linuxは、プログラムにメモリを割り当て、それを開き、実行のためにスケジュールし、メモリ構造を初期化し、提供された引数からexecvp呼び出しへの引数と環境を設定し、バイナリをロードするのに適したハンドラーを見つけてプログラムを準備します、現在のタスク(execvp呼び出し元)を実行しないように設定します。その実装を見つけることができます こちら

上記のすべての手順は、関連する manual pages で説明されているPOSIXで設定された要件に準拠しています。

19

あなたの質問について:

マニュアルページでは、execvpはプロセスイメージのイメージを新しいイメージで置き換えます。ただし、ここでは実行可能ファイルではなくコマンドを実行しています。

昔からシェルは非常に限られており、ほとんどすべてのUNIXコマンドはスタンドアロンの実行可能ファイルでした。現在、主に速度の目的で、UNIXコマンドの一部のサブセットがシェル自体に実装されており、これらのコマンドはbuiltinsと呼ばれています。 typeコマンドを使用して、シェルに組み込まれているコマンドまたは組み込まれていないコマンドを確認できます。

_λ ~/ type echo
echo is a Shell builtin
_

(説明付きのビルトインの完全なリストは、シェルのmanページにあります。例:_man bash-builtins_または_man builtin_。)

しかし、それでもコマンドのほとんどには、実行可能なカウンターパートがまだあります。

_λ ~/ whereis echo
/bin/echo
_

したがって、実行している特定のケースでは:

_char* arg[] = {"ls", "-l", NULL};
execvp(arg[0],arg);
_

実際には、現在のプロセスのアドレス空間を(ほとんどの場合)_/bin/ls_のアドレス空間に置き換えています。


私の直感では、ファイルを読み取る必要があり、それを解析して引数を引数に保存することができます。

確かにあなたが持っています。ただし、「シェバン」とも呼ばれるカーネル内関数を使用することもできます。
別のファイルにファイル名を置く代わりに、catしたいファイルの最初の行として、いわゆるShebangを追加します。

_#!/bin/cat
_

そして、それに_chmod +x_を追加します。その後、実行可能ファイルとして実行できます(exec関数またはシェルのいずれかを使用)。

_λ ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me
λ ~/tmp/ chmod +x cat_me
λ ~/tmp/ ./cat_me 
#!/bin/cat
TEST
_

原因として、Shebang自体をファイルとともに出力するという欠点がありますが、カーネル内でそれを行うのは楽しいです=)

ところで。 (非常に簡単な説明では)stdinを介して渡された引数のリストで指定されたプログラムを実行するxargsという特別な実行可能ファイルがあるほど一般的であると説明した問題。詳細については、_man xargs_に相談してください。


exec- familyを簡単に覚えるために、次の表をよく使用します。

_           Figure 8.14. Differences among the six exec functions
+----------+----------+----------+----------+--------+---------+--------+
| Function | pathname | filename | agr list | argv[] | environ | envp[] |
+----------+----------+----------+----------+--------+---------+--------+
|  execl   |    *     |          |     *    |        |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execlp  |          |    *     |     *    |        |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execle  |    *     |          |     *    |        |         |   *    |
+----------+----------+----------+----------+--------+---------+--------+
|  execv   |    *     |          |          |    *   |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execvp  |          |    *     |          |    *   |    *    |        |
+----------+----------+----------+----------+--------+---------+--------+
|  execve  |    *     |          |          |    *   |         |   *    |
+----------+----------+----------+----------+--------+---------+--------+
|  letter  |          |    p     |     l    |    v   |         |   e    |
+----------+----------+----------+----------+--------+---------+--------+
_

そのため、execvpはファイル名、argv(v)およびenviron(e)。次に、実行可能なfilenameのパスが見つかるまで、catの各パスコンポーネントにPATH(場合によってはfilename)を追加することにより、パス名(別名フルパス)を「推測」しようとします。

execのフードの下で行われていること(継承を含む)についての詳細は、W。Richard StevensとStephen A. Ragoによる Advanced Programming in the UNIX Environment(2nd Edition)にあります 別名APUE2。
UNIXの内部構造に興味がある場合は、おそらく読んでください。

12
SaveTheRbtz

「ls」は単なるコマンドではなく、実際にはプログラムです(ほとんどのコマンドはそうです)。 execvpをそのように実行すると、プログラム全体、そのメモリ、スタック、ヒープなどが概念的に「消去」され、「ls」に渡されて独自のスタックに使用できるようになります。ヒープなど.

つまり、execvpはプログラムを破壊し、別のプログラム(この場合は「ls」)に置き換えます。

2
Verdagon

私の直感では、ファイルを読み取る必要があり、それを解析して引数を引数に保存することができます。しかし、私は確認したい。

あなたの直感はほとんど正しいです。例として使用しているcatユーティリティには、2つの別個のコードパスがあります。

  • 引数としてファイル名が指定されている場合、各ファイルが順番に開かれ、読み取られます。
  • ファイル名が指定されていない場合、標準入力から読み取ります。

この動作は、catユーティリティで具体的に実装されています。それより低いレベルでは実装されていません。特に、execシステムコールの一部ではありません。 execシステムコールは、引数をまったく「見ません」。それらはargvの新しいプロセスに直接渡され、そのプロセスは適切と思われるものを処理します。

1
duskwuff