2

私は C でシェルを書いていますが、execvp(filepath,argv).

ユーザーls -aが現在のディレクトリで実行することを入力した場合...たとえば...そのディレクトリで実行するためのand/home/user1は何でしょうか?filepathargvls

filepathコマンドが実行されるディレクトリでしょうか、/home/user1それともコマンドの場所/bin/lsでしょうか?

4

2 に答える 2

5

へのfilepath引数execvp()は、スラッシュを含むか、スラッシュを含まない 2 つの形式のいずれかを取ることができます。

スラッシュ付き

filepath引数は、絶対名 (スラッシュで始まる) または相対名 (スラッシュで始まらず、スラッシュを含む) のいずれかで、実行可能ファイルのパス名を指定します。関数はexecvp()引数を変更せず、指定されたファイルが存在し、実行可能であると仮定して、プログラムが実行されます (または実行されません)。

スラッシュなし

引数は、 などのfilepath「単純な」名前を指定しますls。次に、関数は、環境変数にリストされているディレクトリの 1 つにexcevp()ある名前のプログラムを実行しようとします。inは、パス ルックアップのように「パス」を表します。ls$PATHpexecvp()

理論の適用

ユーザーls -aがシェルに入力した場合、それを実行する通常の方法は、次と同等の文字ポインターの配列を作成することです。

char *argv[] = { "ls", "-a", 0 };

execvp(argv[0], argv);

execvp()パスベースの分析を行い、 にlsリストされているディレクトリの 1 つから実行を試み$PATHます。

ユーザー/bin/ls -aがシェルに入力した場合、それを実行する通常の方法は、次と同等の文字ポインターの配列を作成することです。

char *argv[] = { "/bin/ls", "-a", 0 };

execvp(argv[0], argv);

execvp()、指定された絶対パス名を実行します。これは、ユーザーが要求したものであるためです (たとえば、/usr/bin/lsまたはとは対照的/usr/local/bin/lsです)。

処理は実際には同じであることに注意してください。コマンド ラインを単語に分割します。各単語は、null ポインターで終了する文字ポインターの配列の要素になり、最初の単語をexecvp()'filepath' 引数として渡し、配列全体を 2 番目の引数として渡します。

明らかに、シェルは実際の実行可能ファイルの場所をキャッシュすることができ、多くのシェルはそれをexecvp()行うため、プログラムを見つけようとする作業を行う必要はありません (シェルは呼び出しませんexecvp()が、通常execv()は実行可能ファイルの絶対パス名で呼び出します. しかし、それは必要ではありません; それは最適化です.

また、あなたの行動を止めるものは何もないことに注意してください:

char *argv[] = { "/honky/tonk/toys", "-a", 0 };
execvp("ls", argv);

実行されるのは実行可能ファイルであるため、今はそうではないargv[0]はずです。何が見つかるかはシステムによって異なりますが(たとえば、Mac OS X ではサポートされていません)、バイナリへのシンボリック リンクは. Linux では、 が元の引数を含んでいるにもかかわらず ( も同様です)、バイナリ名 ( )を報告することがよくあります。これが良いか悪いかはあなたの見方次第ですが、世界の全てが Linux ではありません。"/honky/tonk/toys"lsls/proc/proc/bin/lspsls/proc/PID/cmdlineargv[0]/honky/tonk/toys

于 2013-10-06T05:05:57.857 に答える