2016-03-17 18 views
5

私は、各プロセスがファイルの一部を読み込んで、ファイル内の単語数を数えるためにマルチプロセスプログラムを使っている学校向けのプログラムを作っています。私は2つ以上のプロセスがある場合、すべてのプロセスがファイルの一部を読み取る前にファイルからEOFを読み込む問題が発生しています。 3つのプロセスとファイルを実行しているファイルの最後までEOFに達しました

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 

int main(int argc, char *argv[]) { 

    FILE *input_textfile = NULL; 
    char input_word[1024]; 
    int num_processes = 0; 
    int proc_num = 0; //The index of this process (used after forking) 
    long file_size = -1; 

    input_textfile = fopen(argv[1], "r"); 
    num_processes = atoi(argv[2]); 

    //...Normally error checking would go here 

    if (num_processes > 1) { 

     //...create space for pipes 

     for (proc_num = 0; proc_num < num_processes - 1; proc_num++) { 

      //...create pipes 

      pid_t proc = fork(); 

      if (proc == -1) { 
       fprintf(stderr,"Could not fork process index %d", proc_num); 
       perror(""); 
       return 1; 
      } else if (proc == 0) { 
       break; 
      } 

      //...link up the pipes 
     } 
    } 

    //This code taken from http://stackoverflow.com/questions/238603/how-can-i-get-a-files-size-in-c 
    //Interestingly, it also fixes a bug we had where the child would start reading at an unpredictable place 
    //No idea why, but apparently the offset wasn't guarenteed to start at 0 for some reason 
    fseek(input_textfile, 0L, SEEK_END); 
    file_size = ftell(input_textfile); 
    fseek(input_textfile, proc_num * (1.0 * file_size/num_processes), 0); 

    //read all words from the file and add them to the linked list 
    if (file_size != 0) { 

     //Explaination of this mess of a while loop: 
     // if we're a child process (proc_num < num_processes - 1), then loop until we make it to where the next 
     // process would start (the ftell part) 
     // if we're the parent (proc_num == num_processes - 1), loop until we reach the end of the file 
     while ((proc_num < num_processes - 1 && ftell(input_textfile) < (proc_num + 1) * (1.0 * file_size/num_processes)) 
       || (proc_num == num_processes - 1 && ftell(input_textfile) < file_size)){ 
      int res = fscanf(input_textfile, "%s", input_word); 

      if (res == 1) { 
       //count the word 
      } else if (res == EOF && errno != 0) { 
       perror("Error reading file: "); 
       exit(1); 
      } else if (res == EOF && ftell(input_textfile) < file_size) { 
       printf("Process %d found unexpected EOF at %ld.\n", proc_num, ftell(input_textfile)); 
       exit(1); 
      } else if (res == EOF && feof(input_textfile)){ 
       continue; 
      } else { 
       printf("Scanf returned unexpected value: %d\n", res); 
       exit(1); 
      } 
     } 
    } 

    //don't get here anyway, so no point in closing files and whatnot 

    return 0; 
} 

出力:ここに関連するコードです

All files opened successfully 
Process 2 found unexpected EOF at 1323008. 
Process 1 found unexpected EOF at 823849. 
Process 0 found unexpected EOF at 331776. 

エラーが発生テストファイル:でhttps://dl.dropboxusercontent.com/u/16835571/test34.txt

コンパイルを:

gcc main.c -o wordc-mp 

で実行します。

wordc-mp test34.txt 3 

特定のファイルのみが問題を引き起こしますが、エラーのオフセットはファイルの内容と変わらないように変更され続けます。

+0

を(ジョナサンの推測は正しいかもしれないが、あなたは常に[最小限の完全な検証可能な例]を投稿する必要がありますhttp://stackoverflow.com/help/mcve)を使用してください。 – user3386109

+0

申し訳ありませんが、私はそれを行うことに取り組んで –

+0

@ user3386109完了。リンクは編集テキストにあります。 –

答えて

3

フォークする前にファイルディスクリプタを作成しました。子プロセスはファイル記述子を継承し、これは同じというファイルの説明を親として継承しているため、いずれかの子プロセスに進むと、すべての子プロセスに対してカーソルが前進します。

「男フォーク」から、あなたは確認することができ:

  • The child process is created with a single thread—the one that called fork(). The entire virtual address space of the parent is replicated in the child, including the states of mutexes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be helpful for dealing with problems that this can cause.

  • The child inherits copies of the parent's set of open file descrip‐ tors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent. This means that the two descriptors share open file status flags, current file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)).

+0

私はそれをしましたが、授業中にテストしましたが、子供または親のいずれかで前進することは、他のいずれに進まないことも自分自身でテストしました。さらに、各プロセスがEOFに達したときにファイル内のどの位置にあるのかを知ることができ、それらのどれもファイルの実際の終わりではありません。 –

+0

実際には、ファイルを開いたときに動いてみた。なぜそれがクラスのテストで働いたのか分からないが、とにかく、答えに感謝する!そして最初にそれを書いて申し訳ありません。 –

+1

ご覧のとおり、これはforkのマニュアルページに記載されています。フォークは仮想メモリ(全コピーが作成されます)を保持している間、ファイルディスクリプタはシステムに関連し、ファイルディスクリプタ(ファイルディスクリプションへのポインタ)はコピーされますが、コピーされない同じディスクリプタを参照します。 –

関連する問題