2012-04-04 10 views
1

子プロセスと親プロセスの双方向通信を含むシナリオを実装しました。子プロセスはexecvpを使って別のcプログラム(例えばXYZ)を起動します。 Parentはpipe1の一方の端にデータを書き込み、pipe1の他方の端はchildのstdinに複製します。子供はこのデータを読み、いくつかの操作を行い、データをstdoutに書き戻します。このstdoutは、pipe2の終わりを書き込み、現在はpipe2の読み込み側から親の読み込みに複製されます。外部プログラムXYZは変更されません。従うべきシーケンスは複数の読み取りと書き込みを伴うパイプを使用して、子プロセスと親プロセス間の双方向通信を実装する方法

1)親 2)子供が 3)子供がデータにいくつかの変更を行いPIPE1の重複端部(STDIN)からデータを読み出し、複製さSTDOUT、に戻ってデータを書き込むPIPE1にデータを書き込むありますpipe2の終わりを読み取るために 4)parentはpipe2の読み込み側からデータを読み出そうとします。

上記のシナリオはn回繰り返すことができます。

例 1と上記のシナリオの例)親は、印刷後に)1 2)子供が1を読み込み、変更を行い、 3をstdoutに)modifcations後(1書き込み)今親がバック 4このデータとプリントを読み取り、書き込み、親は2を標準入力に書きます 5)上記のように続きます.....

親がパイプ2の読み込み側からデータを読み取ることができません。その文字通りぶら下がっている。

Imp注:データをもう一度書き込む必要があるため、pipe1の書き込みハンドルを閉じていません。私はハンドルを閉じると、パイプでサポートされていないので、私はそれを再び開くことはできません。

void printing() 
{ 
    int c; 
    do 
    { 
     c = getchar(); 
     printf("%c",c); 
    } while ((c != EOF) && (c != '\n')); 
} 

void main() 
{ 
    printing(); 
    printing(); 
} 

以下のように外部プログラムがある

void Child_write (pid_t Handle); 
void Parent_write (pid_t Handle, char c); 
void Child_read (pid_t Handle); 
void Parent_read (pid_t Handle); 

void main() 
{ 

    pid_t Pid; 
    int writepipe[2],readpipe [2]; 

    pipe(readpipe);    /* Create two file descriptors */ 
    pipe(writepipe);    /* Create two file descriptors */ 

    Pid = fork(); 

    if (Pid == 0)   
    { 
    close(writepipe[1]);    /* closing writepipe's write end */ 
    dup2(writepipe[0],0); close(writepipe[0]);  /* duplicating writepipe's read end to stdin*/ 
    close(readpipe[0]);    /* closing readpipe's read end*/ 
    dup2(readpipe[1],1); close(readpipe[1]);  /* duplicating readpipe's write end to stdout*/  
    Child_read(writepipe[0]);    /* reading data from write pipe read end and then duplicating*/ 

    } 
    else     
    { 
    close(writepipe[0]);    /* closing writepipe's read end */ 
    Parent_write(writepipe[1],'1');   /* pupming data to the writepipe */ 
    close(readpipe[1]);    /* closing the readpipes write end */ 
    Parent_read(readpipe[0]);    /* reading the data which is pumped into readpipe */ 
    //Parent_write(writepipe[1],'2');   /* pupming data to the writepipe */ 
    //Parent_read(readpipe[0]); 

    //Parent_write(writepipe[1],'3'); 
    //Parent_read(readpipe[0]); 
    puts("***** End of parent process*****"); 
    } 
} 

void Child_read(pid_t handle) 
{ 
    static char* command = "./stdoutput"; 
    execvp(command, NULL); 
} 

void Parent_write(pid_t handle, char c) 
{ 
    char Buff[] = {'\n','\n'}; 
    Buff[0] = c; 
    int n_written= write(handle, Buff, strlen(Buff)+1); 

    printf("write function has written %d no of bytes and the data written is %s",n_written,Buff); 

    //close(handle); 
} 

void Parent_read(pid_t handle) 
{ 
    printf("PARENT PROCESS: In Parent_read function\n"); 
    int i=0; 
    int bytes_read = 0; 
    char buffer[1024]= {'\0'}; 
    while (read(handle, buffer, sizeof(buffer)) > 0) 
    { 
     printf("PARENT PROCESS:: In while loop\n"); 
     printf("The character/string read from readend of readpipe (stdout) is %s",buffer); 
    } 
    close(handle); 
} 

以下のように

コードは私が!!!!!!!!!助けてくださいです

+1

あなたがマゾヒズムを感じていない限り、 'popen'を使用してください。一度にこれは単方向通信しか許さなかったが、少なくともメモリが役立つならば、Linuxはかなり長い間双方向性をサポートしていた。 –

+0

@JerryCoffin:私はpopen()に関する知識がありません。名前のないパイプ自体で問題を解決することは可能ですか? – chaitu

答えて

1

FILE *の最初のI/Oコール(ファイルストリーム関数を使用)では、ライブラリはストリームをラインバッファリング、ブロックバッファリング、またはバッファリングしないことを決定します。あなたの場合、stdoutputが始まるとstdoutputは端末ではないので、ストリームはブロックバッファモードになり、printfはバッファで終わります。

にあなたの主な機能を変更

void main() 
{ 
    setvbuf(stdout, NULL, _IONBF, 0); 
    printing(); 
    printing(); 
} 

そして、あなたのprintfの呼び出しは書き込みを生成します。

またsetvbuf manページを見て、straceのを使用することを学ぶshoud:

strace -ff -o test.log ./myprog 

はあなたが何 見るようになる2つのログFIL(親のための1つ、子供用1)を生成しますシステムコールは各プログラムによって作成されます。

-1

実際、Jerry Coffinのコメントによれば、popenを使用する必要があります(双方向配管の場合はp2open、もう1つの場合は1つ、もう1つのシステムの場合もあります)。

あなたが本当に自分でそれをすることを強く望むなら、poll(またはおそらくより古いselect)のような多重化システムコールの使用を強く検討するべきです。それで、どのファイル記述子が読み書きできるかをテストし、それに応じて動作するようになります。

+0

もしpopen()を使ってファイルディスクリプタを作成し、pclose()を使ってファイルディスクリプタを閉じると、同じファイルディスクリプタを再び開くことはできますか? – chaitu

+0

'popen' *ファイル記述子を直接作成しません。 'open'、' dup'、 'pipe'システムコールだけがそれを行います。 'popen'ライブラリ関数は、' fopen'のように、Cライブラリに知られている(内部バッファと内部ファイル記述子を含む) 'FILE *'ハンドル*を提供します。 'fileno'を使って' FILE * 'ハンドルの中でファイル記述子を取得することができます。ファイルディスクリプタは、0ではない、1は標準出力、...は小さい負でない整数です。私はあなたが同じファイル記述子を望んでいる理由を理解していません(私はあなたが混乱していると信じています)。投稿に記載されているシナリオで –

+0

....私は複数の読み取りと書き込み(インターリーブ)する必要があります。したがって、(書き込み、読み取り)セットを成功させるには、データを正常に書き込んだ後に書き込みハンドルを閉じる必要があります。その後、私は同じセットを再度実行する必要がある場合、私は閉じられたファイルディスクリプタを開く必要があります。これは私のための必要性です。書き込みハンドルを閉じないと、読み込みがハングアウトします。 – chaitu

関連する問題