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
_のようにコンソールに出力されますか?私の直感では、ファイルを読み取る必要があり、それを解析して引数を引数に保存することができます。しかし、私は確認したい。
前もって感謝します!
execvp
呼び出しで起こることは次のとおりです。
PATH
で、該当する場合、実行されるファイルを検索します。すべてではないにしても、ほとんどのUNIXライクシステムのコマンドは実行可能ファイルです。そうでない場合はどうなりますか?それを試してみてください。 glibcの仕組み をご覧ください。execve
が呼び出されます。 execve
の一部はlibcで実装されるか、システムコール(Linuxなど)で実装されます。execvp
呼び出しへの引数と環境を設定し、バイナリをロードするのに適したハンドラーを見つけてプログラムを準備します、現在のタスク(execvp
呼び出し元)を実行しないように設定します。その実装を見つけることができます こちら 。上記のすべての手順は、関連する manual pages で説明されているPOSIXで設定された要件に準拠しています。
あなたの質問について:
マニュアルページでは、
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の内部構造に興味がある場合は、おそらく読んでください。
「ls」は単なるコマンドではなく、実際にはプログラムです(ほとんどのコマンドはそうです)。 execvpをそのように実行すると、プログラム全体、そのメモリ、スタック、ヒープなどが概念的に「消去」され、「ls」に渡されて独自のスタックに使用できるようになります。ヒープなど.
つまり、execvpはプログラムを破壊し、別のプログラム(この場合は「ls」)に置き換えます。
私の直感では、ファイルを読み取る必要があり、それを解析して引数を引数に保存することができます。しかし、私は確認したい。
あなたの直感はほとんど正しいです。例として使用しているcat
ユーティリティには、2つの別個のコードパスがあります。
この動作は、cat
ユーティリティで具体的に実装されています。それより低いレベルでは実装されていません。特に、exec
システムコールの一部ではありません。 exec
システムコールは、引数をまったく「見ません」。それらはargv
の新しいプロセスに直接渡され、そのプロセスは適切と思われるものを処理します。