10

Unix用のCで単純なシェルを作成しようとしています。コマンドの解析と実行はすべて実行できましたが、配管に問題があります。問題は、2番目のコマンドの入力用に正しいパイプに接続していないことだと思います。

たとえば、「ls | wc」と入力すると、「wc」コマンドの後に一時停止します。これは、入力を待機しているためだと思います。問題は、dup2(reading [i]、0)を使用していて、正しいパイプに接続されていないことだと思います。

これは少し広い質問だと思いますが、もし私が得ることができる指針があれば、それをいただければ幸いです。これは、新しいプロセスを作成し、それらをパイプしようとするコードです。

    int fileds[2];
    int reading[num_cmds];
    int writing[num_cmds];

    int p;
    for(p=0; p < num_cmds; p++)
    {
        reading[p] = -1;
        writing[p] = -1;
    }

    int j;
    for(j=0; j < num_cmds-1; j++)    //Create pipes for commands
    {
        int fileds[2];
        pipe(fileds);
        reading[j+1] = fileds[0];
        writing[j] = fileds[1];
    }

    int i = 0;
    for(i = 0; i < num_cmds;i++)
    {           
        cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args

        pid_t childpid;
        int status;
        childpid=fork();

        if (childpid >= 0) 
        {
            if (childpid == 0) 
            {               
                if(writing[i] != -1)
                {
                    dup2(writing[i],1);
                    close(writing[i]);
                }

                if(reading[i] != -1)
                {
                    dup2(reading[i],0);
                    close(reading[i]);
                }

                int h;
                for(h = 0; h < num_cmds; h++)
                {
                    close(writing[h]);
                    close(reading[h]);
                }

                if(execvp(cmd_args[0],cmd_args) == -1) 
                {
                    perror("Problem with command");
                    exit(0);
                }
            }
            else 
            {
                wait(&status);
                int m;
                for(m = 0; m < num_cmds; m++)
                {
                    if( writing[m] != -1) close(writing[m]);
                    if( reading[m] != -1) close(reading[m]);
                }
            }
        }
        else 
        {
             perror("fork"); 
             continue;
        }


        input_file[0] = 0;
        output_file[0] = 0;
        run_bg = 0;
    }

}



更新:リチャードのおかげで、私はそれを理解することができました。これは、ファイル記述子を間違った順序で閉じることと、一部をまったく閉じないことの組み合わせでした。これが動作するコードです。

int fileds[2];
    int reading[num_cmds];
    int writing[num_cmds];

    int p;
    for(p=0; p < num_cmds; p++)
    {
        reading[p] = -1;
        writing[p] = -1;
    }

    int j;
    for(j=0; j < num_cmds-1; j++)
    {
        int fileds[2];
        pipe(fileds);
        reading[j+1] = fileds[0];
        writing[j] = fileds[1];
    }

    int i = 0;
    for(i = 0; i < num_cmds;i++)
    {           
        cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg);

        pid_t childpid;
        int status;
        childpid=fork();

        if (childpid >= 0) 
        {
            if (childpid == 0) 
            {               
                if(writing[i] != -1)
                {
                    close(1);
                    dup2(writing[i],1);
                }

                if(reading[i] != -1)
                {
                    close(0);
                    dup2(reading[i],0);
                }

                if(execvp(cmd_args[0],cmd_args) == -1) 
                {
                    perror("Problem with command");
                    exit(0);
                }
            }
            else 
            {

                wait(&status);
                close(writing[i]);

                if(i > 0) 
                {
                    close(reading[i]);
                }
            }
        }
        else 
        {
             perror("fork");
        }


        input_file[0] = 0;
        output_file[0] = 0;
        run_bg = 0;
    }
4

2 に答える 2

3

問題は、ループ内の各プロセスを待ってから、すべてのファイル記述子を閉じることだと思います。これにより、dup2()の次の呼び出しでファイル記述子が無効になり、次のプロセスのstdinが変更されないままになります。

推測ですが、私はコードを実行していません。

于 2009-11-07T23:08:52.273 に答える
0

「ls|wc」と入力すると、wcは期待どおりに動作し、lsコマンドによって出力された単語数を出力します。「|」を使用してコマンドをパイプする場合は注意してください アプリケーションでパイプを作成する必要はありません。最初のコマンドはstdoutに出力する必要があり、2番目のコマンドはの標準からその出力を読み取る必要があります。

于 2009-11-07T23:00:59.317 に答える