PThreads.Consumer-продюсер!печать в разных файлах - PullRequest
0 голосов
/ 16 мая 2018

я пытаюсь реализовать производителя - потребителя с потоками. В моем коде ниже работает хорошо, за исключением точки, где я пытаюсь распечатать в 2 файла. (Один для prod и один для cons). Я использую fclose (stdout),когда я удаляю его внутри производителя, то печать в файле производителя в порядке, но потребители нет. Когда я вообще удаляю, все данные, напечатанные в файле потребителя. Мой вопрос, что я должен попытаться сделать правильно, отпечатки (мне нужен потребительраспечатать в cons.out.txt и продюсер в prod_out.txt). Также я не включил проверку потоков, чтобы сделать это простым, но он работает хорошо.#include "head.h"

circular_buffer cb;  
pthread_mutex_t lock; 
pthread_cond_t cond;  


char * data[6]; //is the data taken from cmd(argv[0-6]) first one is the program the other are parameters


int main(int argc , char *argv[])  { 
    validate(argv,argc); //if command arguments are valid  go on
    for(int i=0; i < argc; i++){
         data[i]=argv[i]; //copy argv array to data array 
    }

    cb_init(&cb,10,sizeof(int)); //initialization of circular buffer for 10 nodes + size of int each node 
    pthread_t cons, prod;  
    void *consumer(), *producer();

    int rc = pthread_mutex_init(&lock, NULL);
    rc = pthread_cond_init(&cond, NULL);

    int id[]={1,2}; //prod id is 1 and cons 2

    rc = pthread_create(&prod, NULL, producer, &id[0]);
        rc = pthread_create(&cons, NULL, consumer, &id[1]);

    rc=pthread_join(prod, NULL); 
    rc=pthread_join(cons, NULL); 

    rc = pthread_mutex_destroy(&lock);
    rc = pthread_cond_destroy(&cond);

    cb_free(&cb); //free allocated memory which is alocated in head
    return 1;

 }  
void *consumer(void * id){
     int  thread_id= *((int*)id); //cast to (int)
     int file;  
     FILE * fp2 = fopen("./cons_out.txt","wb"); //creates new file with "cons_out.txt" name
     int i =10; 
     while(i > 0){
         i--;
         pthread_mutex_lock(&lock); 

         while(isEmpty(&cb)){
            int rc = pthread_cond_wait(&cond,&lock);
         }//end while

         int item=0; // item that will be consumed
         cb_pop_front(&cb,&item);
         file = open("./cons_out.txt", O_APPEND | O_WRONLY, 0777 );//open file as new   
         if( file == -1 ) {//fail to open file
                perror("./cons_out.txt");
                return EXIT_FAILURE;
         }
         fclose(stdout);
         dup2( file, STDOUT_FILENO); //change redirections
         printf("Consumer %d : %d\n",thread_id,item); //print output to file

         pthread_cond_signal(&cond);
         pthread_mutex_unlock(&lock); 

     } //end while

         return NULL;
} //end consumer() 

void *producer(void * id){
     int  thread_id= *((int*)id); //cast to (*int)
     int file1; 
     FILE * fp1 = fopen("./prod_in.txt","wb"); //creates new file with "prod_in.txt" name
     for(int i=0; i<10; i++){ //it produce 10 numbers 
         pthread_mutex_lock(&lock); 

         while(isFull(&cb)){
            int rc = pthread_cond_wait(&cond,&lock);
         }//end while

         int seed=1;
         int item=rand(); // item of this producer
         cb_push_back(&cb,&item); 
         file1 = open("./prod_in.txt", O_APPEND | O_WRONLY, 0777 );//open file as new   
         if( file1 == -1 ) {//fail to open file
            perror("./prod_in.txt");
            return EXIT_FAILURE;
         }
         fclose(stdout);
         dup2( file1, STDOUT_FILENO); //change output 
         printf("Producer %i : %i\n",thread_id,item); //print output to file

         pthread_cond_signal(&cond);
         pthread_mutex_unlock(&lock);
         } //end for 

         return NULL;

} //end Producer();

1 Ответ

0 голосов
/ 16 мая 2018

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

Я склонен думать, что непосредственной причиной ваших проблем является то, что fclose() поток stdout освобождает ресурсы уровня потока, особенно данные буфера и отслеживания состояния,open() описание файлового дескриптора не обеспечивает, а dup2() описание файлового дескриптора в объекте FILE представляет закрытый поток.

Но это сбивает меня с толку, почему вы делаете его таким сложным.Почему в мире гадость с дублирующими файловыми дескрипторами?Ваш производитель и потребитель уже fopen() ищут нужные выходные файлы, каждый из которых получает свой собственный поток, связанный с соответствующим файлом (fp1 и fp2).Мне кажется, что все, что вам нужно сделать, это написать в эти потоки через fprintf(), и т. Д. ., Вместо того, чтобы создавать много проблем вместо использования printf().

Это также было бы более эффективным, так как вам не нужно постоянно открывать и закрывать файлы.Откройте каждый раз в начале, как вы уже делаете, и закройте каждый раз в конце, что вы в настоящее время не можете сделать .

...