2012-03-30 39 views
0

我正在嘗試編寫一個程序,它可以通過線程獲取輸入文件並將包含的項打印到屏幕中。但是,最後一個線程不會意外輸出任何輸出。我無法弄清楚問題所在。我在等你的幫助。Pthread在C中意外執行

每個線程獲取3個參數:inputFile1,inputFile2和targetBuf(可以說它是序列號。)文件被排序,我只是簡單地嘗試按順序打印它們的聯合。只打印正數。

命令行:合併N outfile file1 file2 file3 .... fileN N是輸入文件的數量。

如果我給2個輸入文件(意味着1線程),它的工作原理。如果我給4個文件,然後第一個線程給出輸出,第二個不是。如果我給6個輸入文件,那麼第1和第2個線程會給出輸出,但是第3個不會。

頭文件中有兩個結構體。我把它們粘貼在下面。

//thread information 
struct threadInfo{ 
    pthread_t tid; 
    pthread_attr_t attr; 
}; 
//Beginning thread input 
struct beginThreadInput{ 
    FILE **inputFile1, **inputFile2; 
    int targetBuf; 
}; 
typedef struct threadInfo THREADINFO; 
typedef struct beginThreadInput BEGINT_INPUT; 

主要文件代碼:

 #include <stdio.h> 
     #include <unistd.h> 
     #include <stdlib.h> 
     #include <pthread.h> 
     #include <semaphore.h> 
     #include <sys/types.h> 
     #include <errno.h> 
     #include <sys/mman.h> 
     #include <sys/stat.h> 
     #include <unistd.h> 
     #include <fcntl.h> //for O_ constants 
     #include <sys/stat.h> 
     #include <pthread.h> /* thread library */ 

     #include "merge.h" 



     int main(int argc, char** argv){ 
     int i, k, N; 

     /***FILE INITIALIZATION***/ 
     FILE *output; 
     N = atoi(argv[1]); 
     output = fopen(argv[2], "w"); 
     FILE **inputFileList = ((FILE**)malloc (N * sizeof(FILE*))); 
     printf("int N is %d\n", N); 
     for(i = 0; i<N; i++){ 
      inputFileList[i] = fopen(argv[i + 3], "r"); 
     } 
     //START THREADS 
     BEGINT_INPUT **threadInputList = ((BEGINT_INPUT**) malloc ((N/2)*  sizeof(BEGINT_INPUT*))); 
     THREADINFO **threadInfoList = ((THREADINFO**) malloc ((N/2) *   sizeof(THREADINFO*))); 
     for(i = 0; i< N/2 ; i++){ 
      threadInputList[i] = (BEGINT_INPUT *) malloc (sizeof(BEGINT_INPUT)); 
      threadInfoList[i] = (THREADINFO *) malloc (sizeof(THREADINFO)); 
     } 
     pthread_t tid; 
     pthread_attr_t attr; 
     for(i = 0, k = 0; i < (N/2); i++){ 


      threadInputList[i]->inputFile1 = &(inputFileList[k]); 
      threadInputList[i]->inputFile2 = &(inputFileList[++k]); 
      threadInputList[i]->targetBuf = i; 
      pthread_attr_init(&(threadInfoList[i]->attr)); 
      pthread_create(&(threadInfoList[i]->tid), &(threadInfoList[i]->attr), runBeginningThreads, (void*)threadInputList[i]); 

     } 
     pthread_join((threadInfoList[[(N/2)-1]]->tid), NULL); 
     for(i = 0; i<N; i++){ 
      fclose(inputFileList[i]); 
     } 

     } 

     void *runBeginningThreads(void *input){ 

     BEGINT_INPUT *myInput = (BEGINT_INPUT *)input; 
     int first = -1, second = -1, iseof; 
     printf("Thread number %d\n", myInput->targetBuf); 
     while((second > -2) && (first > -2)){ 
      //read integer values from files 
      if(first == -1){ 
       iseof = fscanf(*(myInput->inputFile1), "%d", &first); 
       if(iseof == EOF){ 
        first = -2;  //means end of file 
       } 
       else if(first < 0) 
        first = -1;  //means waiting for an integer 
      } 
      if(second == -1){ 
       iseof = fscanf(*(myInput->inputFile2), "%d", &second); 
       if(iseof == EOF){ 
        second = -2; 
       } 
       else if(second < 0) 
        second = -1; 
      } 
      //print smaller one 
      if((first != -1) && (second != -1)){ 
       if(((first < second) || (second == -2)) && (first != -2)){ 
        printf("%d\n", first); 
        first = -1; 
       } 
       else if(second != -2){ 
        printf("%d\n", second); 
        second = -1; 
       } 
      } 
     } 
     } 

回答

0

我解決我以下列方式問題。如上所示,我在主函數中打開文件,然後將它們傳遞到相應的線程中。我已經改變了這種方式,並將文件的名稱傳遞給線程並在其中打開相關文件。

此外,雖然通過文件,我犯錯誤,其代碼如下

threadInputList[i]->inputFile1 = &(inputFileList[k]); 
threadInputList[i]->inputFile2 = &(inputFileList[++k]); 

此線在一個循環中運行。這導致輸入序列如下([0,1],[1,2],[2,3],[3,4] ...),因爲我只增加一次k。但是,每個線程需要兩個的inputFiles。所以正確的代碼是這樣的:

threadInputList[i]->inputFile1 = &(inputFileList[k++]); 
threadInputList[i]->inputFile2 = &(inputFileList[k++]); 

我想指出一個問題。我修復了這個代碼的文件名,而不是FILE指針變量,因爲它是在那裏發佈的。但爲了說清楚,我修正了發佈在那裏的代碼的錯誤。感謝您的幫助,大家

2

主要的問題可能是,你只能等待一個線程完成,你從程序關閉所有文件,然後退出之前。

您的程序中還有其他一些額外的複雜問題,可能會簡化。我的意思是當你不需要它時使用額外的指針間接尋址。

這裏有一個小簡單的版本,其中需要沒有不使用額外的指針到指針:

struct beginThreadInput{ 
    FILE *inputFile1, *inputFile2; 
    int targetBuf; 
}; 

/* ... */ 

int main(int argc, char** argv){ 
    /* ... */ 

    BEGINT_INPUT *threadInputList = malloc ((N/2)*  sizeof(BEGINT_INPUT)); 
    THREADINFO *threadInfoList = malloc ((N/2) *   sizeof(THREADINFO)); 

    pthread_t tid; 
    for(i = 0, k = 0; i < (N/2); i++){ 
     threadInputList[i].inputFile1 = inputFileList[k]; 
     threadInputList[i].inputFile2 = inputFileList[++k]; 
     threadInputList[i].targetBuf = i; 
     pthread_create(&(threadInfoList[i].tid), NULL, runBeginningThreads, &(threadInputList[i])); 

    } 
    for(i = 0; i< N/2 ; i++){ 
    pthread_join((threadInfoList[i]->tid), NULL); 
} 

    /* ... */ 

    /* While not strictly needed, you should make it a good 
     habit of freeing all you allocate */ 
    free(threadInfoList); 
    free(threadInputList); 

    return 0; /* You missed this */ 
} 
+0

你是對的。但它不像你所說的,因爲我等待最後一個線程,最後一個線程沒有給出任何輸出。如果我等待所有線程,這種情況不會改變,我已經嘗試過了。如果我們說我們有N個線程,那麼第一個N-1就可以正常工作。有問題的是最後一個。 – Shnkc 2012-03-30 22:37:30

+0

@Shnkc您不能等待您認爲是「最後一個」線程,因爲它們的運行順序可能不是它們的創建順序。請記住,線程是彼此獨立運行的。 – 2012-03-30 22:43:14

+0

Ok Joachim Pileborg。我明白了。正如您所說,我正在編輯上面的發佈代碼。但同樣的問題仍然存在。我希望我能以正確的方式解決它。 – Shnkc 2012-03-30 22:50:59