1. ホーム
  2. c

[解決済み] ls -l "のようなコマンドはexeclでは実行されず、execvpでは動作します。

2022-03-04 21:37:28

質問

以下のコードを execl バリアントを使用します。 ls は動作しますが ls -l は動作しませんが、私の execvp アプローチ lsls-l が動作します。を採用した理由は execl というのは、バイナリのパスが異なる可能性があるからです。 execvp では、そのような機能は提供されていませんでした。理想的には execl にも作用するように ls -l で動作していましたが、現在では ls -l . マニュアルを読んでみましたが、役に立ちませんでした。

void child(int argc, char *argv[MAX_ARGS])
{
        execvp(argv[0], argv);
}


void child(char *argv[], char* path)
{
        execl(path, argv, NULL);
}

解決方法は?

execl() これは、前もって何を実行するのかが正確に分かっている場合にのみ有効です。

execl("/bin/ls", "ls", "-l", (char *)0);
execl("/bin/sh", "sh", "-c", "ls -l", (char *)0);
execl("/bin/ls", "pink elephants", "-l", (char *)0);

などなど。

引数がいくつになるかわからない場合は execvp() の他のメンバのいずれかになります。 execv*() ファミリーを使用します。 また、コマンドのパスを指定することに注意してください。 execvp() は下を検索します。 $PATH しかし execl() はありません。 また、以下のように渡される値を選択することができることに注意してください。 argv[0] .

を採用した理由は execl() のアプローチは、バイナリのパスが異なる可能性があるためです。 execvp() では、そのような機能は提供されていませんでした。

ここの意味がよくわからないのですが。 とは execvp() , 指定することができます。

char *argv[] = { "ls", "-l", 0 };
execvp(argv[0], argv);
execv("/bin/ls", argv);

execvp() を検索します。 ls について $PATH で、最初に見つかったマッチするプログラムを実行します。 2番目は /bin/ls を見ずに $PATH を全く使用しない。

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

execv(argv[0], argv);
execvp(argv[0], argv);

どちらの方法でも動作します。2番目の方法は、実行ファイル名( argv[0] ) にスラッシュが含まれています。


私が混乱するのは execvp(argv[0], argv); を渡すのはなぜですか? argv を第2パラメータとして使用します。では、仮に argv[0]"ls -l" を渡す必要があるのでしょうか? argv を第2パラメータとして使用します。

仮に argv[0] が含まれています。 "ls -l" であれば、問題があります。 ほとんどのシステムには、ファイル " /bin/ls -l または" /usr/bin/ls -l というように、空白が名前の一部になっています。

その exec*() 関数は、プロセスを実行するための低レベルの関数です。 最初の引数は実行されるプログラムを指定します (通常はバイナリですが、以下のような shebang 行を持つスクリプトの場合もあります)。 #!/bin/sh を先頭行とする)。 の場合は execv() または execvp() または execve() または execvpe() と同じように、第2引数は引数のベクトルです。 main() 関数は引数のベクトルを受け取ります(または引数ベクトル、したがって argv ). これは、プログラムへの引数をヌル文字で終端したリストである。 を実行したい場合は ls コマンドにオプション -l に指定する必要があります。 argv の3つの値 "ls" , "-l" とヌルポインタを指定します。

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

を使用すると execl*() 関数は、最初の引数として実行するプログラムを指定し、その後に引数ベクトルが書き出されます。

execl("/bin/ls", "ls", "-l", (char *)0);

引数が10個ある場合は、10個の引数(+ヌルポインタ)を書き出さなければなりません。

での exec*() 関数は、名前が含まれています。

  • l - リスト形式引数
  • v - vector形式の引数
  • p - プログラムのPATH検索を行う(与えられた名前にスラッシュが含まれていない場合)。
  • e - 環境変数のベクトルも取る

これらを組み合わせて、次のようになります。

  • execl()
  • execv()
  • execlp()
  • execle()
  • execvp()
  • execve()

がないのがたまにキズ。 execlpe()execvpe() (ただし、Linuxの拡張機能である execvpe(3) ). また、伝統的に man 2 exec これは少なくとも 1979 年の第 7 版 UNIX™ にまでさかのぼる伝統/遺産です (少なくとも RHEL 5 Linux と Mac OS X 10.7.5 までは継承されていました。 man 2 execl のページでは execve() が、Synopsisセクションに記載されていない)。 その他の exec*() の上に構築することができます。 execve() - は、その集合の基本的な関数である(と記載されている)。 execve(2) というように、Linuxのマニュアルに書かれている)。