2012-01-10 7 views
0

私は2人の子供と1つの親が欲しいです。プロセス間のパイプチェーン

親はファイル "a.txt"から読み取り、トラフパイプを最初の子に送信します。最初の子は文字を読み取り、2番目の子に下位の文字を送信します。

2番目の子は、それぞれ異なるcharと出現回数(1行につき)を "b.txt"で出力し、親にパイプを通って別個の文字数を送ります。親は2番目の子からの結果を出力します。

私はパイプを親から1子にしてテストしましたが、パイプを親に戻しました。 私がそれを理解できないのは、パイプを2番目の子供に行く方法です。私はdup2の情報を探していましたが、それを動作させる方法はありません。

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <ctype.h> 
#include <fcntl.h> 

void main() 
{ 

    int pfd1[2], pfd2[2], pid1, pid2, pfin, status, fd; 
    char *c = (char *)malloc(sizeof(char)); 

    if (pipe(pfd1) < 0) { 
     printf("Eroare la crearea pipe-ului\n"); 
     exit(1); 
    } 
    if (pipe(pfd2) < 0) { 
     printf("Eroare la crearea pipe-ului\n"); 
     exit(1); 
    } 
    if ((pid1 = fork()) < 0) { 
     printf("Eroare la fork\n"); 
     exit(1); 
    } 

    if (pid1 == 0) { /*child */ 
     close(pfd1[1]); 
     while (read(pfd1[0], c, 1) > 0) { 
      //printf("%s",c); 
      if (islower(*c)) { 
       close(pfd2[0]); 
       //inchid capul de citire; scriu in pipe 
       write(pfd2[1], c, 1); 
       ////dup?????? 
      } 
     } 
     printf("\n"); 
     write(pfd[1], buff, len); 

     close(pfd1[0]); 
     close(pfd2[1]); 
     exit(0); 
    } 

    if ((pid2 = fork()) < 0) { 
     printf("Eroare la fork\n"); 
     exit(1); 
    } 

    if (pid2 == 0) { 
     printf("second child"); 
     exit(0); 
    } 

    /* parent */ 
    close(pfd1[0]); 
    close(pfd2[1]); 
    fd = open("date.txt", O_RDONLY); 
    while (read(fd, c, 1) > 0) { 
     write(pfd1[1], c, 1); 
    } 
    close(pfd1[1]);  /* la sfarsit inchide si capatul utilizat */ 
    close(pfin); 

    while (read(pfd2[0], c, 1) > 0) 
     printf("%s", c); 
    close(pfd2[0]); 
    printf("%d", wait(&status)); 
    printf("%d", wait(&status)); 

} 

答えて

2

私はあなたのコードのいくつかの具体的なコメントがあります。これは何も問題はありませんが

char *c = (char *)malloc(sizeof(char)); 

を、ヒープから割り当てられるこのcharのための必要もありません。より慣用的なアプローチではchar c;を使用し、次に&cread(2)write(2)システムコールを渡します。 (さらに慣用的なのは、C標準IO機能を使用することです; freopen(3)getchar(3)、およびputchar(3) - このコードは問題が複雑になるので、あなたが望むように正確に動作するまで移行しないでください)解決するようにしています。

if ((pid1 = fork()) < 0) { 
    printf("Eroare la fork\n"); 
    exit(1); 
} 

重要なエラー情報が表示されます。代わりにエラーメッセージを出力するには、perror(3)を使用する必要があります。これにより、実際にという理由でが検索される可能性があります。ユーザーがsetrlimit(2)NPROCの最大プロセス制限(カーネルメモリからシステム全体のプロセス制限)を実行している場合、fork(2)が失敗する可能性があります。

if ((pid1 = fork()) < 0) { 
    perror("Eroare la fork"); 
    exit(1); 
} 

また、open(2)コールの戻り値もチェックする必要があります。 (あなたもエラーwrite(2)close(2)からの戻り値をチェックするためにを想定しているが、これらのエラーを処理することは困難である。単にエラーを印刷して終了すると、ほとんどのプログラムのための良いスタートです。)

while (read(pfd1[0], c, 1) > 0) { 
     //printf("%s",c); 
     if (islower(*c)) { 
      close(pfd2[0]); 

このclose(2)コールの場所が間違っています - すべての入力文字に対してこのfiledescriptorを何度も閉じてはいけません。 close(2)の戻り値をチェックしていた場合、ファイルディスクリプタは2回目以降の呼び出しで無効になるため、errnoEBADFに設定されます。 pipe()fork()のシーケンス、およびパイプラインのすべてのプロセスをフックアップし、親プロセスに戻ってデータを送信しますdup2()呼び出し:

は今、問題にあなたがのためにここに来ました。 pipe(2)は単方向pipe(7)を作成するので、pipe(2)と4回を呼び出す必要があります。親と子の間の両方向です。あなたに何かを意味する名前の配列にパイプの終点を格納すると、それらを追跡するのがより簡単になります。あなたが実際にあなたがにしない限りに他のプログラムを実行して再手配ファイルディスクリプタにdup2(2)を使用するを必要としないこと

int to_child[2]; 
int from_parent[2]; 
int to_parent[2]; 
int from_child[2]; 

for (int i=0; i<2; i++) { 
    int p[2]; 

    if (pipe(p) == -1) { 
    perror("pipe"); 
    exit(1); 
    } 

    /* from parent to child */ 

    to_child[i] = p[1]; 
    from_parent[i] = p[0]; 

    if (pipe(p) == -1) { 
    perror("pipe"); 
    exit(1); 
    } 

    /* from child to parent */ 

    to_parent[i] = p[1]; 
    from_child[i] = p[0]; 
} 

注:おそらくから読み取るためにとfrom_を書き込むためto_という名前の配列を作成します「フィルタ」タスクを処理します。 from_parent[...]またはfrom_child[...]記述子を使用し、write(2)to_child[...]およびto_parent[...]記述子を使用すると、ちょうどread(2)になります。

たぶん全体の事は、その後から読み取られ、他のBSDスタイルのソケットと同じように書き込むことができる双方向ソケットを作成するAF_UNIXを使用してsocketpair(2)と容易になるだろう。概要については、socket(7)およびunix(7)を参照してください。

0

dup()は不要です。単に親のパイプを開いて、次に各プロセスでclose()必要のないエンドポイントを開き、必要なエンドポイントを使用してください。

これは、親が子 - 子通信用のパイプの両端を閉じることを意味することに注意してください。このパイプの各エンドポイントは、いずれかの子によって使用されます。各子は、使用しないエンドポイントも閉じてください。

0

ありがとうございました。 ここに問題全体のコードがあります。

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <ctype.h> 
#include <fcntl.h> 

void main() 
{ 

int pfd1[2],pfd2[2],pfd3[2],pid1,pid2,status,fd,fo; 
char letter[32][2]; 
int letternumber=0,i,sw=0; 
char* c = (char*)malloc(sizeof(char)); 
//pipe creation 
if(pipe(pfd1)<0){ 
    perror("Eroare la crearea pipe-ului"); 
    exit(1); 
} 

if(pipe(pfd2)<0){ 
    perror("Eroare la crearea pipe-ului\n"); 
    exit(1); 
} 

if(pipe(pfd3)<0){ 
    perror("Eroare la crearea pipe-ului\n"); 
    exit(1); 
} 
//make first child 
if((pid1=fork())<0){ 
    perror("Eroare la fork\n"); 
    exit(1); 
} 
if(pid1==0) //child process 
{ 
if(close(pfd1[1])<0) {perror("Eroare close");exit(1);} // close write end; process will read from pipe 
if(close(pfd2[0])<0) {perror("Eroare close");exit(1);} //close read end; write in pipe 
while (read(pfd1[0], c, 1) > 0){ 
    if(islower(*c)) write(pfd2[1],c,1);//writing in pipe 

} 
if(close(pfd1[0])<0) {perror("Eroare close");exit(1);} /* close other ends */ 
if(close(pfd2[1])<0) {perror("Eroare close");exit(1);} 
if(close(pfd3[0])<0) {perror("Eroare close");exit(1);} 
if(close(pfd3[1])<0) {perror("Eroare close");exit(1);} 
exit(0); 
} 


//make second child 
if((pid2=fork())<0){ 
    perror("Eroare la fork"); 
    exit(1); 
} 

if(pid2==0){ /* second child*/ 
     if(close(pfd1[0])<0) {perror("Eroare close");exit(1);} 
    if(close(pfd1[1])<0) {perror("Eroare close");exit(1);} 
    if((fo=open("statistica.txt", O_CREAT | O_TRUNC | O_RDWR, 
       S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | 
       S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IROTH))==-1) 
    {perror("Eroare open");exit(1);} 
    if(close(pfd2[1])<0) {perror("Eroare close");exit(1);} 
    letter[0][0]='A'; 
    letter[0][1]=0; 
    while(read(pfd2[0],c,1)>0) {   
    for(i=0;i<=letternumber;i++) 
      if(letter[i][0]==*c) {letter[i][1]++;sw=1;} 
    if (sw==0){ 
      letter[letternumber][0]=*c; 
      letter[letternumber++][1]=1; 
    }  
    sw=0;  
    } 
    printf("\n");//why won't it write to file without it; 
        //wihtout it, it writes to screen? 
    if(close(pfd2[0])<0) {perror("Eroare close");exit(1);} 
    dup2(fo,1); 
    for(i=0;i<letternumber;i++) 
     printf("%c %d\n",letter[i][0],letter[i][1]); 
    if(close(fo)<0) {perror("Eroare close");exit(1);} 
    if(close(pfd3[0])<0) {perror("Eroare close");exit(1);} //close read end; going to write in pipe 
    dup2(pfd3[1],1); 
    printf("%d",letternumber); 
    if(close(pfd3[1])<0) {perror("Eroare close");exit(1);} 
    exit(0); 
} 

/* parent process */ 
if(close(pfd1[0])<0) {perror("Eroare close");exit(1);} // close read end; write in pipe 
if(close(pfd2[0])<0) {perror("Eroare close");exit(1);} 
if(close(pfd2[1])<0) {perror("Eroare close");exit(1);} 
if(close(pfd3[1])<0) {perror("Eroare close");exit(1);} 

if((fd=open("date.txt",O_RDONLY))==-1) 
    {perror("Eroare open");exit(1);} 

while(read(fd,c,1)>0) 
     write(pfd1[1],c,1); //write in pipe 

if(close(pfd1[1])<0) {perror("Eroare close");exit(1);} 
//dup2(pfd3[0],0); 
while(read(pfd3[0],c,1)>0) printf("%c",*c); 
printf("\n"); 
if(close(pfd3[0])<0) {perror("Eroare close");exit(1);} 
wait(&status); 
wait(&status); 
}