2012-03-30 36 views
0

unerwartet ausgeführt Ich versuche, ein Programm zu schreiben, das Eingabedateien erhält und enthaltene Elemente durch Threads in den Bildschirm druckt. Der letzte Thread gibt jedoch keine Ausgabe unerwartet. Ich konnte nicht herausfinden, was das Problem ist. Ich warte auf deine Hilfe.Pthread wird in C

Jeder Thread bekommt 3 Parameter: inputFile1, inputFile2 und targetBuf (nehmen wir an, es ist Sequenznummer.) Dateien sind sortiert, ich versuche einfach, ihre Vereinigung in der Reihenfolge zu drucken. Es werden nur positive Zahlen gedruckt.

Befehlszeile: Merge N Dateidatei1 Datei2 Datei3 .... DateiNr N ist die Anzahl der Eingabedateien.

Wenn ich 2 Eingabedateien geben (bedeutet 1 Thread), funktioniert es. Wenn ich 4 Dateien gebe, gibt der 1. Thread die Ausgabe, die zweite nicht. Wenn ich 6 Eingabedateien gebe, geben die ersten und zweiten Threads die Ausgabe an, die dritte jedoch nicht.

Es gibt zwei Strukturen in der Header-Datei. Ich habe sie unten eingefügt.

//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; 

Main-Datei Code:

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

Antwort

0

ich meine Frage in der folgenden Art und Weise zu lösen. Wie oben zu sehen, öffne ich die Dateien in der Hauptfunktion und gebe sie dann in entsprechende Threads weiter. Ich habe diesen Weg geändert und die Namen der Dateien in Threads übergeben und zugehörige Dateien darin geöffnet.

Zusätzlich, während Dateien vorbei, ich war, Fehler zu machen, sein Code unter

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

Diese Zeilen in einer Schleife ausgeführt werden. Dies verursacht eine Eingabesequenz wie folgt ([0,1], [1,2], [2,3], [3,4] ...), da ich k nur einmal inkrementiere. Jeder Thread benötigt jedoch zwei von Eingabedateien. Also der korrekte Code ist dies:

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

Ich möchte auf ein Problem hinweisen. Ich habe diesen Code für Dateinamen korrigiert, nicht für FILE-Pointer-Variablen, wie sie dort gepostet werden. Aber um es klar zu machen, habe ich den Fehler auf einen Code behoben, der dort gepostet wurde. Danke für Ihre Hilfe, alle

2

Das Hauptproblem könnte sein, dass Sie nur warten auf einen Thread, zu beenden, bevor Sie alle Dateien zu schließen und beenden Sie dann aus dem Programm.

Es gibt ein paar andere zusätzliche Komplikationen in Ihrem Programm, die wahrscheinlich vereinfacht werden könnten. Ich meine, dass Sie extra Zeigerindirection verwenden, wenn Sie es nicht wirklich brauchen.

Hier ist eine kleine einfachere Version, nicht mit zusätzlichen Zeiger-to-Zeiger, wo keine nötig sind:

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

Sie haben Recht. Aber es ist nicht so, wie du gesagt hast, weil ich auf den letzten Thread warte und der letzte Thread keine Ausgabe liefert. Wenn ich auf alle Threads warte, ändert sich diese Situation nicht, ich habe es bereits versucht. Wenn wir sagen, dass wir N Threads haben, funktioniert die erste N-1 von ihnen korrekt. Der problematische ist der letzte. – Shnkc

+0

@Shnkc Sie können nicht auf das warten, was Sie denken, ist der "letzte" Thread, da die Reihenfolge, in der sie ausgeführt werden, nicht die Reihenfolge ist, in der sie erstellt werden. Denken Sie daran, dass Threads unabhängig voneinander ausgeführt werden. –

+0

Ok Joachim Pileborg. Ich verstehe. Ich bearbeite den oben genannten Code sofort, wie Sie es gesagt haben. Aber das gleiche Problem existiert immer noch. Ich hoffe, ich konnte es richtig regeln. – Shnkc