0

私は研究室に取り組んでいます。親プロセスは、2 つの子プロセス A および B を作成します。子 A は、パイプを介して子 B に文字列を送信します。子 B は、子 A から取得した文字列の文字列ケースを反転し、反転した文字列を子 A に送り返します。反転文字列 son A を受け取ると、それが画面に出力されます。

これがコードです。

#include <stdio.h>   
#include <unistd.h>   
#include <stdlib.h>
#include <ctype.h>   

void process_A(int input_pipe[], int output_pipe[])
{
    int c;    
    char ch; 
    int rc;  


    close(input_pipe[1]); 
    close(output_pipe[0]); 

    while ((c = getchar()) > 0) {
        ch = (char)c;
        rc = write(output_pipe[1], &ch, 1);
    if (rc == -1) { 
        perror("A_TO_B: write");
        close(input_pipe[0]);
        close(output_pipe[1]);
        exit(1);
        }

    rc = read(input_pipe[0], &ch, 1);
    c = (int)ch;
    if (rc <= 0) { 
        perror("A_TO_B: read");
        close(input_pipe[0]);
        close(output_pipe[1]);
        exit(1);
        }
    putchar(c);
    }
    close(input_pipe[0]);
    close(output_pipe[1]);
    exit(0);
}

void process_B(int input_pipe[], int output_pipe[])
{
    int c;   
    char ch; 
    int rc;   
    close(input_pipe[1]); 
    close(output_pipe[0]); 
    while (read(input_pipe[0], &ch, 1) > 0) {
        c = (int)ch;
        if (isascii(c) && isupper(c))
            c = tolower(c);
          else if (isascii(c) && islower(c))
            c = toupper(c);
        ch = (char)c;
        rc = write(output_pipe[1], &ch, 1);
        if (rc == -1) {
            perror("B_TO_A: write");
            close(input_pipe[0]);
            close(output_pipe[1]);
            exit(1);
        }
    }

    close(input_pipe[0]);
    close(output_pipe[1]);
    exit(0);
}


int main(int argc, char* argv[])
{
    /* 2 arrays to contain file descriptors, for two pipes. */
    int A_TO_B[2];
    int B_TO_A[2];
    int pid;       
    int rc,i,State;       

    /* first, create one pipe. */
    rc = pipe(A_TO_B);
    if (rc == -1) {
    perror("main: pipe A_TO_B");
    exit(1);
    }
    /* create another pipe. */
    rc = pipe(B_TO_A);
    if (rc == -1) {
    perror("main: pipe B_TO_A");
    exit(1);
    }

    for(i=0;i<2;i++)
    {
        if((pid=fork()) <0){perror("fork failed\n");};
        if((i==0) && (pid ==0))
        {
            process_A(A_TO_B, B_TO_A); 
        }
        else if((i==1)&&(pid==0))
        {
            process_B(B_TO_A, A_TO_B); 
        }
        else if(pid>0)
        {
           wait( &State );          
        }   
    }

    return 0;   
}

問題は、プログラムを実行すると、Son B がブロックされることです。皆さんの助けが必要です。前もって感謝します。

4

1 に答える 1

2

OK、図:

initially: parent process: has
  B_TO_A[0] and [1] open,
  has A_TO_B[0] and [1] open
fork (makes copy)
parent:                                child (pid==0):
B_TO_A both open, A_TO_B both open     call process_A: close unwanted pipe ends, loop

call wait(), wait for one child        loop reads stdin, writes one pipe, reads other pipe

if we ever get here:

fork (makes copy)
parent:                                child (pid==0):
B_TO_A both open, A_TO_B both open     call process_B: close unwanted pipe ends, loop

parent: both ends of both pipes open
call wait(), wait for one child        loop reads one pipe, writes other pipe

process_A()まず、実行中の子は、stdin で EOF (最初に発生した場合) またはパイプの読み取り/書き込み呼び出しのいずれかが失敗する (たとえば、EOF が原因で) までループ内で実行されるため、通常は「ここに到達した場合」には到達しません。オンinput_pipe[0])。親はまだ wait() 呼び出しで待機しており、両方のパイプの両端が開いているため、パイプに EOF はありません (パイプの EOF は、すべてのライターによって書き込まれたすべてのデータを読み取った後に発生しdup、書き込み終了が閉じられました)。したがって、そこに到達する唯一の方法は、whileループが実行されないように、stdin で EOF をヒットすることです。

第二に、再度 fork してprocess_B(). 親は で永久に待機するため、親はそれを閉じませんwait

一般に、ここで行う必要があるのは次のとおりです。

  • 2 つのパイプを作成します (今のように)
  • 一度フォークprocess_A()して、子で実行します
  • (親で) 再度 fork しprocess_B()、(新しい) 子で実行します。
  • 両方のパイプの両端を閉じます (親で)
  • 両方の子が開始された後、両方の子を待ちます

2 番目の子を開始できない場合は、何か (kill()最初の子など) を行う必要があるため、エラー処理は少し面倒です。そのため、どこまで進んだかを知る必要があります。ループして fork を 2 回行うことはできますが、ループ内ではできませんwait。また、ループを 2 回回るだけで、それぞれがかなり異なる手順を実行するため、ループなしですべてを書き出すこともできます。

于 2012-03-19T19:59:59.747 に答える