Pthread在C中意外执行

时间:2012-03-30 22:24:15

标签: c multithreading file-io pthreads

我正在尝试编写一个程序,它通过线程获取输入文件并将包含的项目打印到屏幕上。但是,最后一个线程不会意外地给出任何输出。我无法弄清楚问题是什么。我在等你的帮助。

每个线程获得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;
                }
            }
        }
      }

2 个答案:

答案 0 :(得分: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 */
}

答案 1 :(得分:0)

我用以下方式解决了我的问题。如上所示,我打开main函数中的文件,然后将它们传递给相应的线程。我已经改变了这种方式,并将文件的名称传递给线程并打开其中的相关文件。

此外,在传递文件时,我犯了错误,其代码在

之下
 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指针变量,因为它是在那里发布的。但为了说清楚,我修复了那里发布的代码的错误。谢谢你的帮助,每个人