2

いくつかの基本的な機能を備えた独自の Linux シェルを実装しようとしていますが、もちろん、パイプを実装するときに問題が発生します。より具体的に言えば、パイプはほとんどの部分で機能しますが、最後の引数を削除するようです。たとえば、コマンドを実行する場合

ps ax | grep ps

grep コマンドの後の ps がシェルにドロップされます。したがって、典型的な Linux シェルを使用して、示されているようにこれを出力する代わりに

339 ?        S      0:00 upstart-udev-bridge --daemon
497 ?        Ss     0:00 /usr/sbin/cupsd -F
503 ?        S<     0:00 [kpsmoused]
720 ?        S      0:00 upstart-socket-bridge --daemon
5541 pts/0    R+     0:00 ps ax
5542 pts/0    S+     0:00 grep --colour=auto ps

あなたはこれを得る

339 ?        S      0:00 upstart-udev-bridge --daemon
497 ?        Ss     0:00 /usr/sbin/cupsd -F
503 ?        S<     0:00 [kpsmoused]
720 ?        S      0:00 upstart-socket-bridge --daemon
5557 pts/0    R+     0:00 ps ax

この場合、一致するパターン ps を検索していません。

配管の機能は次のように実行されます

void mypipes(char* args[], int nargs)
{
  pid_t pid;
  int fd[2];

  char* cmdargs[nargs - 2];
  char* cmdargs2[nargs - 2];


  int i;
  int t = 0;
  int count = 0;

  for(i = 0; i < nargs; i++)
  {
if(!strcmp(args[i], "|"))
{
    //dont put into array
    t = 1;
}
else if(t == 0)
{
    cmdargs[i] = args[i];
    count++;
}
else if(t == 1)
{
    cmdargs2[i - 3] = args[i];
}
  }


  if(count == 2)
  {
  pipe(fd);
  pid = fork();

  if(pid == -1)
  { 
    perror("unable to fork");
    exit(1);
  }
  if(pid > 0)
  {
    wait(&pid);
    close(fd[1]);
    close(0);
    dup2(fd[0],0);
    execlp(cmdargs2[0], cmdargs2[0], cmdargs2[1], NULL);
  }
  if(pid == 0)
  {
    close(fd[0]);
    close(1);
    dup2(fd[1],1);
    execlp(cmdargs[0], cmdargs[0], cmdargs[1], NULL);
  }
  }

  if(count == 1)
  {
  pipe(fd);
  pid = fork();

  if(pid == -1)
  { 
    perror("unable to fork");
    exit(1);
  }
  if(pid > 0)
  {
    wait(&pid);
    close(fd[1]);
    close(0);
    dup2(fd[0],0);
    execlp(cmdargs2[0], cmdargs2[1], NULL);
  }
  if(pid == 0)
  {
    close(fd[0]);
    close(1);
    dup2(fd[1],1);
    execlp(cmdargs[0], cmdargs[1], NULL);
  }

  }

}

パイプの後のすべての変数がまだ2番目の引数セット内にあるかどうかを確認しましたが、それらは問題がメインではなく、最後まで読み取らない実際のパイピングを実行している場所です.

ここで何が間違っている可能性があるかについてのヒントを事前にありがとう.

4

1 に答える 1

1

まず、何かが欠けていない限り、2 つのサンプル出力はどちらも機能しているように見えます。どちらも「ps」を含む行のみをリストしています。(実際に実行されている場合ps ax | grepgrep、使用について文句を言うでしょう)。出力で確認できる唯一の違いは、2 番目にプロセス自体がリストされていないことですが、が開始される前にプロセス リストの取得が完了しているgrep場合、これは簡単に発生する可能性があります。psgrep

第二に、あなたの使用wait(&pid)は奇妙です-それはプロセスにあるため、子プロセスの子のいずれかが終了するのを待ちます。何もないので、それは戻ります(もしあれば、孫の終了ステータスでECHILD上書きされます)。pid

3 番目にtcmdargsと をcmdargs2一緒に使用して、countどのexeclp呼び出しを行うかを決定するのは、それが次の形式の場合にのみ機能しcmd1 arg1 | cmd2 arg2ます。他のほとんどの組み合わせは機能しません。いくつかのポイント:

  • パイプの後に引数を保存する代わりに[i -3]、どの位置でパイプを見たかを覚えておく必要があります (たとえば、パイプを見つけてその後に引数を保存するときにの代わりにt=1使用します)。t=i+1cmdargs2[i-t]
  • execvp()引数の配列を渡すことができるように、関数呼び出しのバージョンを確認する必要があります (コマンドラインからのすべての引数の後に NULL 要素を追加することを忘れないでください)。
于 2013-07-17T20:42:49.670 に答える