0

現在、Linuxシェルの入力コマンドを受け取り、それらを実行して子プロセスを作成するプログラムに取り組んでいます。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char * argv[])
{ 
  int pid, status;
  if (argc < 2) {
    printf("Usage: %s command, [arg1 [arg2]...]\n", argv[0]);
    return EXIT_FAILURE;
  }
  printf("Starting %s...\n", argv[1]);
  pid = fork();
  if (pid == 0) {
    execvp(argv[1], &argv[1]);
    perror("execvp");
    return EXIT_FAILURE; // Never get there normally
  } else {
    if (wait(&status) == -1) {
      perror("wait");
      return EXIT_FAILURE;
    }
  }
  return EXIT_SUCCESS;
}

のような入力で動作し./program command argますが、たとえば次のような引数を使用してさまざまなコマンドを受信する必要があります。./program command arg command arg .....

助言がありますか?

4

4 に答える 4

0

ここでの質問はargvの解析だと思います。

ダミーの論理フローは次のとおりです。

    for(i = 1; i < argc; i++)
    {
        isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
        if (isCommand)
        {
            for(; i < argc; i++)
            {
                isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
                if (isNotCommand)
                {
                    PushOption(argv[i]); /* save options */
                } else
                {
                    /* Get Command and options from stack */
                    /* execute command with fork/execv */
                }
            }
        } 
    }

ここで必要なのは、CheckCmdとPushOption/PopOptionを実現することだけです。

于 2011-12-06T06:42:07.453 に答える
0

実際に何が問題なのかはわかりませんが、フォークされた各プロセスがパラメーターをどのように消費するかを理解するのに問題があると思います。

argvフォークするたびに、ポインターを次のコマンド/引数のペアに進める必要があると思います。この fork ループは、コマンドがゼロ ターミネータの場合に終了します。

この問題のどの側面で立ち往生しているかを実際に述べていないため、質問を理解できたことを願っています。

于 2011-05-05T20:37:52.960 に答える
0

argcのサイズを教えてくれますargv

argvその情報を使用してそれらを抽出する必要があります。

これは、引数の数が異なるコマンドの問題を解決しないことに注意してください。

コメントへの返信でその理由を編集します。

getopt()これを行うことができるのは次のとおりです。

 ./program -c "command arg1 arg2" -c "command arg1" ...

問題は、コマンド/引数セットを区別できる必要があることです。getopt()少なくとも途中まで到達する場合は、各セットを解析するだけです。それがあなたの唯一の入力タイプなので、それは本当にやり過ぎですが。この場合、反復argv処理は同じくらい簡単です。

別のオプションは、区切り記号でそれらを区切ることです。

./program command arg1, command arg1 arg2, ... 

コマンド/引数のセットが完了したことを確認するには、反復しargvてコンマを探す必要があります。または、すべての argv を文字列に連結して使用しますstrtok()。ちょっと醜い私見ですが、実行可能です。

于 2011-05-05T20:39:04.943 に答える
0

シェルは複雑なソフトウェアです。最近、オペレーティング システム クラス用にシェルを実装する必要がありましたが、それは困難でした。また、入力ごとに 1 つのコマンドを制御するだけで済みました (ただし、I/O リダイレクトとパイプを実装する必要があり、手動でパス検索を行ってから で実行する必要がありましたexecv())。

あなたが直面する問題は、コマンド ライン パラメーターの配列内の次の引数文字列がコマンドなのか前のコマンドの引数なのかを判断する方法がまったくないことにあります。コマンドとその引数を区別できる唯一の方法は、それが交互になることがわかっcommand arg command arg ...ている場合、またはコマンドごとに他の標準化された数の引数がある場合 (これはあまり役に立ちません)、またはセミコロンのようなコマンド間に区切り記号がある場合です。command arg; command arg arg arg; ...

交互になることがわかっている場合は、次のように引数をループできます。

for(int i = 1; i < argc; i += 2)
{
   //command is argv[i], arg is argv[i + 1]
}

これを行うためのより良い方法は、コマンド ライン パラメーターを使用する代わりに、入力プロンプトを作成し、通常のシェルの使用と同様に、1 行ごとに 1 つのコマンドを処理することです。

于 2011-05-05T20:41:25.087 に答える