Pthread выполняется неожиданно в C - PullRequest
0 голосов
/ 31 марта 2012

Я пытаюсь написать программу, которая получает входные файлы и печатает включенные элементы на экране по потокам.Тем не менее, последний поток не дает неожиданного вывода.Я не мог понять, в чем проблема.Я жду вашей помощи.

Каждый поток получает 3 параметра: inputFile1, inputFile2 и targetBuf (допустим, это порядковый номер.) Файлы отсортированы, я просто пытаюсь напечатать их объединение по порядку.Печатаются только положительные числа.

Командная строка: объединить N outfile file1 file2 file3 .... fileN N - количество входных файлов.

Если я даю 2 входных файла (означает 1 поток), оно работает.Если я даю 4 файла, то 1-й поток дает вывод, 2-й нет.Если я даю 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 ]

2 голосов
/ 31 марта 2012

Основная проблема может заключаться в том, что вы ожидаете завершения одного потока, прежде чем закрыть все файлы и затем выйти из программы.

В вашей программе есть несколько дополнительных сложностей, которые, возможно, можно было бы упростить. Я имею в виду, что вы используете дополнительную косвенную указатель, когда она вам действительно не нужна.

Вот немного более простая версия, без использования дополнительных указателей на указатели, где они не нужны:

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 голосов
/ 05 апреля 2012

Я решаю свой вопрос следующим образом.Как видно выше, я открываю файлы в функции main, а затем передаю их в соответствующие потоки.Я изменил этот способ и передал имена файлов в потоки и открыл в них связанные файлы.

Кроме того, при передаче файлов я допускал ошибки, его код был ниже

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

Эти строки выполняются в цикле.Это приводит к входной последовательности, подобной следующей ([0,1], [1,2], [2,3], [3,4] ...), потому что я увеличиваю k только один раз. Однако каждый поток занимает двавходных файлов.Итак, правильный код таков:

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

Я хочу указать на проблему.Я исправил этот код для имен файлов, а не для переменных-указателей FILE, поскольку он размещен там.Но чтобы прояснить ситуацию, я исправил ошибку в размещенном там коде.Спасибо всем за помощь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...