2017-01-30 2 views
0

この有名な問題に問題がありました。 私は、パイプのおかげで通信する2人の子供(プロデューサーとコンシューマー)をフォークする必要があります。 最初の子(プロデューサ)はstdinから文字列を読み取って、大文字に変換してstdoutに出力する必要がある2番目の子(コンシューマ)に送信する必要があります。プロデューサー - 2人の子どもの間の消費者が[C]

コードを書きましたが、動作しません。

  • コンシューマは、stdinから文字列を読み取り、その長さの隣のパイプ( '\ 0'を含む)に書き込みます。
  • プロデューサはパイプからMAXCを読み取り、2つの可変長と文字列で分割します。印刷すると長さが大きくなります。だから、変換されなければならない文字列でさえ、正しくはありません。さらに、プログラム全体がフリーズします。

は(私はここでコードを書くことを試みたが、多分私はそれを正しく行う方法を理解していなかった私に説明していただきありがとうございます。!)編集

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/wait.h> 
#define MAXC 30 
static void signalHandler(int signo) 
{ 
    return; 
} 
pid_t pids[2]; 
int main() 
{ 
    int fd[2], i, nW; 
    size_t l; 
    char string[MAXC+1], stringtoup[MAXC+1], tmp[MAXC+1]; 

    signal(SIGUSR1, signalHandler); 
    if(pipe(fd)==0) 
    {  
     pids[0]=fork(); 
     if(pids[0]==0) 
    { 
     fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
     close(fd[0]); //produttore 
     sleep(3); 
     fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
     fscanf(stdin, "%s", string); 
     while(1) 
     { 
      if(strcmp(tmp, "end")==0) 
     break; 
      l=strlen(string)+1; 
      sprintf(tmp, "%2lu%s", l, string); 
      printf("%s\n", tmp); 
      nW=write(fd[1], tmp, (l+2)); 
      printf("nW(PRODUCER)=%d", nW); 
      if(nW!=(l+2)) 
     { 
      perror("wrote not whole string"); 
      exit(1); 
     } 
      sleep(5); 
      kill(pids[1], SIGUSR1); 
      pause(); 
      fprintf(stdout, "Insert string:\n"); 
      fscanf(stdin, "%s", string); 
     } 

     exit(0); 
    } 
     pids[1]=fork(); 
     if(pids[1]==0) 
    { 
     fprintf(stdout, "PID=%d CONSUMER\n", getpid()); 
     close(fd[0]); //consumer 

     while(1) 
     { 
      pause(); 
      read(fd[0], tmp, MAXC+1); 
      printf("tmp(CONSUMER)=%s\n", tmp); 
      sscanf(tmp, "%2lu%s", &l, stringtoup); 
      printf("lenght string(CONSUMER)=%2lu\n", l); 
      printf("stringtoup=%s\n", stringtoup); 
      for(i=0; i<l; i++) 
     stringtoup[i]=toupper(stringtoup[i]); 

      fprintf(stdout, "%s\n", stringtoup); 
      fflush(stdout); 
      sleep(1); 
      kill(pids[0], SIGUSR1); 
     } 
     exit(0); 
    } 

     sleep(4); 
     for(i=0; i<2; i++) 
    { 
     waitpid(pids[i], NULL, 0); 
     fprintf(stdout, "PID=%d exited\n", pids[i]); 
    } 

    } 
    return(0); 
} 

:コードは固定

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/wait.h> 
#define MAXC 30 

pid_t pids[2]; 
int main() 
{ 
    int fd[2], i, nW; 
    size_t l; 
    char string[MAXC+1], stringtoup[MAXC+1], tmp[MAXC+1]; 

    if(pipe(fd)==0) 
    {  
     pids[0]=fork(); 
     if(pids[0]==0) 
    { 
     fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
     close(fd[0]); //produttore 
     fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
     fscanf(stdin, "%s", string); 
     while(1) 
     { 
      if(strcmp(string, "end")==0) 
     break; 
      l=strlen(string)+1; 
      sprintf(tmp, "%2lu%s", l, string); 
      nW=write(fd[1], tmp, (l+2)); 
      if(nW!=(l+2)) 
     { 
      perror("wrote not whole string"); 
      exit(1); 
     } 
      sleep(1); 

      fscanf(stdin, "%s", string); 
     } 
     kill(pids[1], SIGINT); 
     exit(0); 
    } 
     pids[1]=fork(); 
     if(pids[1]==0) 
    { 
     fprintf(stdout, "PID=%d CONSUMER\n", getpid()); 
     close(fd[1]); //consumer 

     while(1) 
     { 
      read(fd[0], tmp, MAXC+1); 
      sscanf(tmp, "%2lu%s", &l, stringtoup); 
      for(i=0; i<l; i++) 
     stringtoup[i]=toupper(stringtoup[i]); 

      fprintf(stdout, "%s\n", stringtoup); 
      fflush(stdout); 
      sleep(1); 
     } 
     exit(0); 
    } 

     for(i=0; i<2; i++) 
    { 
     waitpid(pids[i], NULL, 0); 
     fprintf(stdout, "PID=%d exited\n", pids[i]); 
    } 
    } 
    return(0); 
} 
+2

コードを表示していないことを考慮すると、どのような回答が期待されますか?あなたの質問にコードを含めるには、それを[編集]してコードを追加し、Ctrl-Kを押してコードの書式を追加します。 –

+0

完了。お手伝いありがとう! – Zanarkand

+0

'close(fd [0]);にあります。 // consumer'それは 'fd [1]'でなければなりません。 – user58697

答えて

2

コメントを読むことで、私は質問が変更され、kill-wait手順に関係すると思います。

問題は、子がフォークしたときから親のメモリと何の関係もないことです。このプロセスは、独自のメモリの一部を変更することがないようにpids[1]の値が変化しない

pids[0] == 0; 
pids[1] == undefined; 

:として

最初の子(プロデューサー)が充填されたpids配列を有しています。

pids[0] == first_child's pid; 
pids[1] == 0; 

すべてのすべては、親のみが第二子(pids[1]との1)を殺すことができる、ではない最初の子:

第二子(消費者)として埋めpidsアレイを有します。だから、「プロデューサー」はあなたが知らないpidでプロセスを殺します(それは幸運でなければより広いシステム問題を引き起こす可能性がある)ので、「消費者」は決してそれを取得しません。

パイプにライターがない場合、read()関数はゼロ(0)を返します。それはあなたが何を利用するべきか、起こったときに中断して終了することです。一方、ライターが存在するときは、読み取るべきものがあるまでread()機能ブロックをブロックするので、sleep(1)は必要ありません。

私が見ることができるように、ランダムプロセスの強制終了が実行されたときにプログラムが失敗するため、親プロセスが子プロセスの終了を表示しないのはこのためです。ただし、そのkill(...)を削除する場合は、パイプの書き込み終了を閉じて、戻り値がread(...)であることを確認して、プログラムを実行します。

また、必要でないすべてのfdsを閉じるパターンがあります(終了機能がある時点でそれを行うにもかかわらず)。したがって、すべての子を生成した直後の親は2fdsを閉じることができます(読者が壊れるためにはの書き込み終了を閉じなければなりません!)、読者は終了する前に残りのfdを閉じることができます。下には、修正が必要なコードの部分があります。

... 
if(pids[0]==0)     
      {           
        fprintf(stdout, "PID=%d PRODUCER\n", getpid()); 
        close(fd[0]); //produttore        
        fprintf(stdout, "Insert strings (max 30 chars), finish with 'end':\n"); 
        fscanf(stdin, "%s", string);           
        while(1)                 
        {                       
          if(strcmp(string, "end")==0)                   
            break;                          
          l=strlen(string)+1;                       
          sprintf(tmp, "%2lu%s", l, string);                      
          nW=write(fd[1], tmp, (l+2));                          
          if(nW!=(l+2))                                
          {                                       
            perror("wrote not whole string");                                           exit(1); 
          }                                                   sleep(1); 
                                                             fscanf(stdin, "%s", string); 
        }                                        
        close(fd[1]); 
        exit(0); 
      } 
      pids[1]=fork(); 
      if(pids[1]==0) 
      {    
        fprintf(stdout, "PID=%d CONSUMER\n", getpid());           
        close(fd[1]); //consumer  

        while(1)           
        {                
          if (read(fd[0], tmp, MAXC+1) == 0) 
            break; 
          sscanf(tmp, "%2lu%s", &l, stringtoup); 
          for(i=0; i<l; i++)             
            stringtoup[i]=toupper(stringtoup[i]);          

          fprintf(stdout, "%s\n", stringtoup); 
          fflush(stdout); 
          sleep(1); // this could be removed 
        } 
        close(fd[0]); 
        exit(0); 
      } 

      close(fd[0]); 
      close(fd[1]); 
      for(i=0; i<2; i++) 
... 
関連する問題