2016-03-17 14 views
5

Tôi đang tạo một chương trình cho trường học ở đó tôi có một chương trình đa xử lý trong đó mỗi quá trình đọc một phần của tệp và chúng hoạt động cùng nhau để đếm số từ trong tệp. Tôi đang gặp vấn đề nếu có nhiều hơn 2 quy trình, thì tất cả các quy trình đọc EOF từ tệp trước khi họ đọc phần của tệp. Dưới đây là các mã có liên quan:EOF đã đạt được trước khi kết thúc tệp

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

Output khi chạy các tập tin với 3 quá trình:

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. 

Các tập tin thử nghiệm gây ra lỗi: https://dl.dropboxusercontent.com/u/16835571/test34.txt

Compile với:

gcc main.c -o wordc-mp 

và chạy dưới dạng:

wordc-mp test34.txt 3 

Cần lưu ý rằng chỉ có tệp cụ thể đó mới cho tôi vấn đề, nhưng bù trừ lỗi tiếp tục thay đổi nên không phải nội dung của tệp.

+0

đoán Jonathan có thể là đúng, nhưng bạn luôn nên viết [Minimal Hoàn Verifiable Ví dụ] (http://stackoverflow.com/help/mcve) khi yêu cầu trợ giúp gỡ lỗi. – user3386109

+0

Được rồi, tôi sẽ làm việc để hoàn tất công việc đó –

+0

@ user3386109 Xong. Liên kết nằm trong văn bản chỉnh sửa. –

Trả lời

3

Bạn đã tạo bộ mô tả tệp của mình trước khi tắt. Một tiến trình con thừa kế bộ mô tả tệp trỏ đến cùng một mô tả tệp của cha/mẹ và do đó, hãy tiến lên với một trong các con làm cho con trỏ tiến lên cho tất cả trẻ em.

Từ "người đàn ông ngã ba", bạn có thể có thư xác nhận:

  • 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

Tôi đã làm điều đó, nhưng chúng tôi đã kiểm tra trong lớp và tôi cũng đã thử nghiệm bản thân rằng tiến bộ trong cả hai đứa trẻ hoặc cha mẹ không tiến bộ trong bất kỳ của những người khác.Thêm vào đó, bạn có thể thấy vị trí của từng quá trình trong tệp khi nó đến EOF và không có vị trí nào trong số đó là phần cuối thực của tệp. –

+0

Thực tế đã đi trước và thử di chuyển khi tôi mở tệp và nó đã sửa nó. Không chắc chắn lý do tại sao nó làm việc trong các bài kiểm tra trong lớp học, nhưng dù sao, cảm ơn bạn đã trả lời! Và xin lỗi vì đã viết nó đi ban đầu. –

+1

Như bạn có thể thấy, đây là tài liệu trong trang người đàn ông của ngã ba. Trong khi forking bảo tồn bộ nhớ ảo (toàn bộ bản sao được tạo), các bộ mô tả tập tin có liên quan đến hệ thống và bộ mô tả tập tin (là con trỏ đến một mô tả tập tin) được sao chép nhưng tham khảo cùng một mô tả (không được sao chép). –

Các vấn đề liên quan