3

execvp を使用して ls|wc を実行しようとしています。そこで、パイプを作成してからフォークして子を作成します。親/子の適切な (読み取り/書き込み) エンドを閉じてから、もう一方のエンドを stdout/stdin にマップします。次に、execvp を使用して親で ls を実行し、子で wc を実行します。プログラムを実行すると、

 wc:standard input:bad file descriptor.
 0 0 0
 wc: -:Bad file descriptor

これが私のコードです:

int main()
{
//int nbBytes = 0; //stream length
int pfd_1[2]; //file descriptor 
//char buffer[MAX_FILE_LENGTH]; 
char* arg[MAX_FILE_LENGTH];
pid_t processPid;

//Create a pipe

if(pipe(pfd_1) == -1)
{
    printf("Error in creating pipe");
    return 0;
}

//Create a child
processPid = fork();

if(processPid == -1)
{
    printf("Erro in fork");
    exit(1);
}   
else if(processPid == 0) //Child
{               
    //redirect read end file descriptor to standard input
    dup2(pfd_1[0],0);
    //Close the write end
    if(close(pfd_1[1] == -1))
    {
        printf("Error in closing the write end file descriptor");
        exit(1);
    }
    arg[0] = "wc";
    //arg[1] = "-l";
    arg[1] = '\0';

    if(execvp(arg[0],arg) == -1)
    {
        printf("Error in executing ls");
    }       

}
else //Parent
{               
    //redirect standard output to the file descriptor
    dup2(pfd_1[1],1);
    //Close the read end
    if(close(pfd_1[0] == -1))
    {
        printf("Error in closing the read end from parent");
        exit(1);
    }
    //Command 
    arg[0] = "ls";
    arg[1] = "/proc/1/status";
    arg[2] = '\0';

    if(execvp(arg[0],arg) == -1)
    {
        printf("Error in executing ls");
    }       
}

}

何が間違っているのでしょうか?標準入力を不適切なファイル記述子と見なすのはなぜですか? 私の理解は、標準入力と読み取り終了ファイル記述子がエイリアスであるため、 wc -l は親プロセスからの出力を読み取るためです。標準入力から読み取るには scanf を実行する必要がありますか?

4

2 に答える 2

1

問題は次の行にあります。

if(close(pfd_1[1] == -1))

の結果を閉じていますpfd_1[1] == -1。これは必然的に に等しくなり0ます (決して等しくならないため)。正しい行はおそらく次のようになります。

if (close(pfd_1[1]) == -1)

親プロセスで読み取り側を閉じようとするときに、後でこれを再度行うことに注意してください。

于 2013-01-13T05:19:41.490 に答える
0

子に行く場合は、「ゾンビ」の子プロセスを避けるために、親プロセスforkを呼び出す必要があります。wait()したがって、元のプロセスの fork を実行した親プロセスを、 を介して別の実行可能ファイルでオーバーレイする必要はありませんexec

一連のパイプを必要な方法でセットアップする簡単な方法の 1 つは、実行する実行可能ファイルごとに子をフォークし、そのデータを親のバッファーに読み戻すことです。次に、そのデータを最初の子から、親が分岐した新しい子プロセスにフィードします。そのため、各子プロセスは親プロセスからデータを受け取り、データを処理し、そのデータを親プロセスに書き戻します。親プロセスは、変換されたデータをバッファに格納します。そのバッファは、次の子などに供給されます。バッファ内のデータの最終結果は、パイプの最終出力です。

ここに小さな疑似コードがあります:

//allocate buffer
unsigned char buffer[SIZE];

for (each executable to run in pipeline)
{
    pipes[2];
    pipe(pipes);

    pid_t pid = fork();

    if (pid == 0)
    {
        //setup the pipe in the child process
        //call exec
    }
    else
    {
        //setup the pipe in the parent process

        if (child executable is not the first in the pipeline)
        {
            //write contents of buffer to child process
        }

        //read from the pipe until the child exits
        //store the results in buffer

        //call wait, and maybe also check the return value to make sure the 
        //child returned successfully
        wait(NULL);

        //clean up the pipe
    }
}
于 2013-01-13T05:21:22.583 に答える