2012-03-30 37 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