0

私は 2 人の子供を持つ 1 つの親を持ちたいです。

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

2番目の子は、「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));

}
4

3 に答える 3

2

私はあなたのコードにいくつかの特定のコメントがあります:

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

これに問題はありませんが、これcharをヒープから割り当てる必要もありません。より慣用的なアプローチでは、 char c;here を使用し&cてからread(2)write(2)システム コールに渡します。(さらに慣用的には、C 標準 IO 機能を使用することfreopen(3)です。解決しようとしています。)getchar(3)putchar(3)

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

独自のエラー メッセージを使用すると、重要なエラー情報を見逃すことになります。perror(3)代わりに、エラー メッセージを出力するために使用する必要があります。これにより、あなたとあなたのユーザーは、検索できるエラーの実際の原因を知ることができます。ユーザーが最大プロセス制限 (システム全体のプロセス制限) にカーネル メモリを使い果たしてfork(2)いる場合、失敗する可能性があります。setrlimit(2) NPROC

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)呼び出しの場所が間違っています。入力文字ごとにこのファイル記述子を何度も閉じるべきではありません。戻り値をチェックしていた場合、ファイル記述子が 2 回目以降の呼び出しで有効でなくなるため、が に設定されていることclose(2)に気付くでしょう。errnoEBADF

ここで、あなたがここに来た問題について説明します:パイプライン内のすべてのプロセスをフックし、データを親プロセスに送り返すfork()pipe()、および呼び出しのシーケンスです。は一方向の を作成するdup2()ため、親と子の間の双方向で4 回呼び出す必要があります。パイプ エンドポイントを、自分にとって意味のある名前を付けて配列に格納すると、追跡しやすくなります。おそらく、書き込み用および読み取り用の名前の付いた配列を作成します。pipe(2)pipe(7)pipe(2) to_from_

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];
}

「フィルター」タスクを処理するために他のプログラムを実行したい場合を除き、ファイル記述子を再配置するために実際にを使用する必要はないことに注意してください。または記述子と および 記述子を使用するだけです。dup2(2)read(2)from_parent[...]from_child[...]write(2)to_child[...]to_parent[...]

socketpair(2)おそらく、 を使用AF_UNIXして双方向ソケットを作成すると、全体が簡単になり、他の BSD スタイルのソケットと同じ方法で読み書きできるようになります。概要については、socket(7)およびを参照してください。unix(7)

于 2012-01-11T00:24:39.673 に答える
0

必要ありませんdup()。親でパイプを開き、各プロセスclose()で不要なエンドポイントを開き、必要なエンドポイントを使用するだけです。

これは、親が子と子の通信のためにパイプの両方のエンドポイントを閉じることを意味することに注意してください。このパイプの各エンドポイントは、子の 1 つで使用されます。各子は、使用しないエンドポイントも閉じる必要があります。

于 2012-01-11T21:06:45.737 に答える
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);
}
于 2012-01-12T12:09:12.630 に答える