2

Linux でタスクを実行していますが、うまくいきません。

テキストファイルをパラメーターとして受け取るプログラムがあります。fork()次に、パラメーターとして受け取ったテキスト ファイルの内容を 1 行ずつ使用して子プロセスを作成し、子プロセスに送信します。子プロセスは行数を数え、受信した行数を親プロセスに返す必要があります。

これは私が今まで持っていたものですが、子プロセスがすべての行を受け取るわけではありません。私のテストでは、9 行のテキスト ファイルを使用しました。親は 9 行を文字列として送信しましたが、子プロセスはそのうちの 2 ~ 3 行しか受信しませんでした。

私は何を間違っていますか?

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{  
  char string[80];
  char readbuffer[80];
  int pid, p[2];
  FILE *fp;
  int i=0;
  if(argc != 2)
  {
    printf("Syntax: %s [file_name]\n", argv[0]);
    return 0;    
  }
  fp = fopen(argv[1], "r");
  if(!fp) 
  {    
    printf("Error: File '%s' does not exist.\n", argv[1]);
    return 0;
  }
  if(pipe(p) == -1)
  {
    printf("Error: Creating pipe failed.\n");
    exit(0);
  } 
  // creates the child process
  if((pid=fork()) == -1)
  {
   printf("Error: Child process could not be created.\n");
    exit(0);
  }  

  /* Main process */
  if (pid) 
  { 
    // close the read
    close(p[0]);    
    while(fgets(string,sizeof(string),fp) != NULL)
    {                
       write(p[1], string, (strlen(string)+1));
       printf("%s\n",string);
    } 

    // close the write
    close(p[1]);
    wait(0);
  }

  // child process
  else 
  {   
    // close the write
    close(p[1]); 

    while(read(p[0],readbuffer, sizeof(readbuffer)) != 0) 
    {
      printf("Received string: %s\n", readbuffer);    
    }

    // close the read
    close(p[0]); 
  } 
  fclose(fp);       
}
4

5 に答える 5

4

パイプは、一方向のプロセス間通信チャネルです。2 つのパイプを作成する必要があります。1 つは子プロセスと通信するため、もう 1 つはデータを読み戻すためです。

両方のプロセスでパイプの未使用側を閉じることを忘れないでください。

于 2012-05-26T18:23:56.897 に答える
4

null ターミネータを他のプロセスに送信しています。

   write(p[1], string, (strlen(string)+1));

受け取ったものを印刷すると、null ターミネータまでしか表示されないため、結果が混乱します。

代わりにこれを行う場合:

   write(p[1], string, strlen(string));

期待どおりの結果が得られるはずです。

于 2012-05-26T15:12:32.947 に答える
1

パイプのマンページ( man 2 pipe )を調べてください。あなたが書こうとしているプログラムはそこにある例です。あなたのものと比較してください:)

于 2012-05-26T15:07:06.030 に答える
1

行数を数えているのではなく、戻ってきた回数を数えていread(2)ます。

パイプを使用する場合、read(2)パイプから可能な限り多くのデータを取得します: min(pipe_available, space_available). 改行、バイトなどは気にしません0。機能させるための簡単なトリック:

  • ループを使って歩いreadbufferて探す\n
  • fdopen+を使用fgets(これにはおそらく欠陥があると感じています)
于 2012-05-26T15:04:37.200 に答える
0

ご提案いただきありがとうございます。これは私が今持っているもので、うまくいきますが、答えを親に送り返すにはどうすればよいですか? 親プロセスが答えを必要とするためです。

if (pid) /* Main process */
  { 
    /* Close the read */
    close(p[0]);    
    while(fgets(string,sizeof(string),fp) != NULL)
    {   
    write(p[1], string, (strlen(string)));    
    }    
    /* Close the write */
    close(p[1]);
    wait(0);
    printf("\nMain process with PID=%d has terminated succesfully.\n", getpid());
   }
   else /* Child process */
   {   
     /* Close the write */
     close(p[1]);    
     while( read(p[0], readbuffer, sizeof(readbuffer)) > 0) 
     {
       int j=0;
       for(j; j<sizeof(readbuffer); j++)
       {    
       if (readbuffer[j] == '\n')
       { 
          i++;    
       }
        }  
      }
      /* Close the read */
      close(p[0]); 
      printf("\nChild process with PID=%d has terminated succesfully.\nChild process received %d lines from the parent process.\n",getpid(), i);
    } 
于 2012-05-26T18:11:42.330 に答える