Reallo c ошибка, ошибка чтения из канала, ошибка закрытия канала - PullRequest
0 голосов
/ 27 мая 2020

Я пытался написать код на C, используя вилки и каналы, где программа создает четыре процесса, которые взаимодействуют друг с другом через каналы. Связь основана на следующем дереве связи:

  1
 / \
 2 3
 \ /
  |
  4

Первый процесс считывает n слов из файла с именем input.dat , где n дается как аргумент. Первый процесс отправляет слова второму и третьему процессу, используя разные каналы.

Второй процесс читает слова из конвейера и считает все гласные слово за словом. Если количество гласных четное, процесс заменяет каждую гласную на пару из двух (никаких изменений не требуется в случае нечетного числа), а затем присоединяет количество гласных к каждому слову.
Я уже задавал вопрос по этому поводу, вот ссылка с примерами: Как посчитать количество гласных в файле пословно и прикрепить результаты к словам?

Третий процесс делает то же самое, за исключением согласных.

И второй, и третий процесс используют один и тот же конвейер для отправки измененных слов четвертому процессу, который распечатает изменение в файл с именем output.dat .

После каждого процесса чтения, записи или модификации процессы распечатывают свой pid вместе с тем, что они сделали с файлом с именем log.dat

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

Вот код:


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stddef.h>

int str_count_in_chars(char *start, char *end, char *chars) {
    int count = 0;

    for (; start != end; count += !!strchr(chars, *(start++)));

    return count;
}

void str_swap_in_chars(size_t str_len, char **str, char *chars) {
    int front,back;
    for ( front = 0, back = str_len - 1; front < back; front++) {
        if (strchr(chars, (*str)[front])) {
            for (; !strchr(chars, (*str)[back]); back--);

            char tmp = (*str)[front];
            (*str)[front] = (*str)[back];
            (*str)[back--] = tmp;
        }
    }
}

char *file_to_str(FILE *fin,int n) {
    int buf_len = 64;
    char buf[buf_len];
    char *str = malloc(buf_len);
    str[0] = '\0';
    int i;
    for (i = 1; i <= n; i++) {
    fgets(buf, buf_len, fin);
        if (!(str = realloc(str, i * buf_len))) {
            fprintf(stderr, "%s:%d realloc failed\n", __FILE__, __LINE__);
            exit(1);
        }

        strcat(str, buf);
    }

    return str;
}
int main(int argc, char *argv[]){
    int pfd[2],pfd1[2],pfd2[2];

    FILE *f =fopen("log.dat","w");

    if(argc<2)
    {
        printf("Usage:\n%s <number>\n",argv[0]);
        exit(1);
    }

    char *p=argv[1];
    while(*p != '\0')
    {
      if(*p<'0' || *p>'9')
      {
       printf("%s is not a number!\n",argv[1]);
       exit(1);
      }
      p++;
    }


    int n = atoi(argv[1]);
    FILE *g;

    if(pipe(pfd) == -1)
    {
        printf("Error opening first pipe\n");
        exit(1);
    }   

    if(pipe(pfd1) == -1)
        {
                printf("Error opening second pipe\n");
                exit(1);
        }

    if(pipe(pfd2) == -1)
        {
                printf("Error opening third pipe\n");
                exit(1);
        }



    /*child1*/
    switch(fork())
    {
        case -1:
            printf("Error forking child1!\n");
            exit(1);
        case 0:
            /*closing unnecessary pipe ends*/
            if(close(pfd[1]) == -1)
            {
                printf("Error closing writing end of first pipe\n");
                exit(1);
            }
            if(close(pfd1[0]) == -1)
            {
                printf("Error closing reading end of second pipe\n");
                exit(1);
            }
            if(close(pfd1[1]) == -1)
                        {
                                printf("Error closing writing end of second pipe\n");
                                exit(1);
                        }
            if(close(pfd2[0]) == -1)
            {
                printf("Error closing reading end of third pipe\n");
                exit(1);
            }

            /*reading from first pipe*/
            char *words1=" ";
            ssize_t numRead;    
            numRead=read(pfd[0],words1,strlen(words1));
            if(numRead == -1);
            {
                printf("Error reading from first pipe\n");
                exit(1);
            }

            fprintf(f,"First child pid_%d received data from parent pid_%d\n",getpid(),getppid());
            fflush(f);

            /*closing reading end of first pipe*/
            if(close(pfd[0]) == -1)
            {
                printf("Error closing reading end of first pipr\n");
                exit(1);
            }

            /*counting vowels from received words*/
            /*if even, swapping them in pairs*/
            /*concatenating each word with the number of vowels*/
            char *vowels = "aeiou";
            int i;
            char *words2=" ";
            for(i = 0; i < strlen(words1); )
            {
                if(isspace(words1[i]))
                {
                sprintf(words2,"%s",words1[i++]);
                continue;
                }

                int start = i;

                for (; i < strlen(words1) && !isspace(words1[i]); i++);

                    char *word = words1 + start;
                    int word_len = i - start;
                    int vowel_count = str_count_in_chars(word, words1 + i, vowels);

                     if (vowel_count % 2 == 0) {
                          str_swap_in_chars(word_len, &word, vowels);
                     }
                sprintf(words2,"%.*s_%dvow",word_len,word,vowel_count);
            }       

            fprintf(f,"First child pid_%d made the needed modifications\n",getpid());
            fflush(f);

            /*sending the words to third child*/
            ssize_t stat;
              stat=write(pfd2[1],words2,strlen(words2));
             if(stat<0)
                  {
                        printf("Error writing to third pipe!\n");
                        exit(1);
                   }


            fprintf(f,"First child pid_%d sent the modified data to third child",getpid());
            fflush(f);

            /*closing writing end of third pipe*/
            if(close(pfd2[1]) == -1)
                        {
                                printf("Error closing writing end of third pipe\n");
                                exit(1);
                        }



        default:
            break;
    }


    /*child2*/
    switch(fork())
    {
        case -1:
                        printf("Error forking child1!\n");
                        exit(1);
                case 0:
            /*closing unnecessary pipe ends*/
            if(close(pfd[0]) == -1)
            {
                printf("Error closing reading end of first pipe\n");
                exit(1);
            }
            if(close(pfd[1]) == -1)
                        {
                                printf("Error closing writing end of first pipe\n");
                                exit(1);
                        }
            if(close(pfd1[1]) == -1)
                        {
                                printf("Error closing writing end of second pipe\n");
                                exit(1);
                        }
            if(close(pfd2[0]) == -1)
                        {
                                printf("Error closing reading end of third pipe\n");
                                exit(1);
                        }

             /*reading from second pipe*/
                        char *words3=" ";
            ssize_t numRead;
                        numRead=read(pfd1[0],words3,strlen(words3));
            if(numRead == -1)
                        {
                                printf("Error reading from second pipe\n");
                                exit(1);
                        }

                        fprintf(f,"Second child pid_%d received data from parent pid_%d\n",getpid(),getppid());
                        fflush(f);

            /*closing reading end of second pipe*/
                        if(close(pfd1[0]) == -1)
                        {
                                printf("Error closing reading end of second pipe\n");
                                exit(1);
                        }

            /*counting consonants from received words*/
                        /*if even, swapping them in pairs*/
                        /*concatenating each word with the number of consonants*/
            char *cons = "qwrtypsdfghjklzxcvbnm";
                        int i;
                        char *words4=" ";
                        for(i = 0; i < strlen(words3); )
                        {
                                if(isspace(words3[i]))
                                {
                                sprintf(words4,"%s",words3[i++]);
                                continue;
                                }

                                int start = i;

                                for (; i < strlen(words3) && !isspace(words3[i]); i++);

                                char *word = words3 + start;
                                int word_len = i - start;
                                int cons_count = str_count_in_chars(word, words3 + i, cons);

                                 if (cons_count % 2 == 0) {
                                  str_swap_in_chars(word_len, &word, cons);
                                 }
                                sprintf(words4,"%.*s_%dvow",word_len,word,cons_count);
                        }


                        fprintf(f,"Second child pid_%d made the needed modifications\n",getpid());
                        fflush(f);

                        /*sending the words to third child*/
            ssize_t stat;
            stat=write(pfd2[1],words4,strlen(words4));
            if(stat<0)
                          {
                                printf("Error writing to third pipe!\n");
                                exit(1);
                           }


                        fprintf(f,"Second child pid_%d sent the modified data to third child",getpid());
                        fflush(f);

                        /*closing writing end of third pipe*/
                        if(close(pfd2[1]) == -1)
                        {
                                printf("Error closing writing end of third pipe\n");
                                exit(1);
                        }

                default:
                        break;

    }


    /*child3*/
    switch(fork())
    {
        case -1:
                        printf("Error forking child1!\n");
                        exit(1);
                case 0:
            /*closing unnecessary pipe ends*/
                        if(close(pfd[0]) == -1)
                        {
                                printf("Error closing reading end of first pipe\n");
                                exit(1);
                        }
                        if(close(pfd[1]) == -1)
                        {
                                printf("Error closing writing end of first pipe\n");
                                exit(1);
                        }
                        if(close(pfd1[1]) == -1)
                        {
                                printf("Error closing writing end of second pipe\n");
                                exit(1);
                        }
            if(close(pfd1[0]) == -1)
                        {
                                printf("Error closing reading end of second pipe\n");
                                exit(1);
                        }

                        if(close(pfd2[1]) == -1)
                        {
                                printf("Error closing writing end of third pipe\n");
                                exit(1);
                        }

            /*reading from third pipe*/
            char *words5=" ";
            FILE *h = fopen("output.dat","w");
            ssize_t numRead;

            numRead=read(pfd2[0],words5,strlen(words5));
            if(numRead == -1)
                        {
                                printf("Error reading from third pipe\n");
                                exit(1);
                        }

                        fprintf(f,"Third child pid_%d received data\n",getpid());
                        fflush(f);

            /*closing reading end of third pipe*/
            if(close(pfd2[0]) == -1)
            {
                printf("Error closing reading end of third pipe\n");
                exit(1);
            }

            /*printing received content to file*/
            if(h)
            {
                fputs(words5,h);
            }
            else { printf("Failed to open file\n");}

            fclose(h);

            fprintf(f,"Third child pid_%d printed data to file\n",getpid());
            fflush(f);
                default:
                        break;

    }

    /*parent*/

       if(close(pfd[0]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }
        if(close(pfd1[0]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }
        if(close(pfd2[0]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }
        if(close(pfd2[1]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }


    g = fopen("input.dat","r");

    /*reading n words from file and sending it to child1 and child2*/
    char *words = file_to_str(g,n);
    printf("%s\n",words);   
    int words_len = strlen(words);
    ssize_t stat;
    stat=write(pfd[1],words,words_len);
    if(stat<0)
    {
        printf("Error writing to first pipe!\n");
        exit(1);
    }

    if(close(pfd[1]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }

    fprintf(f,"parent pid_%d sent data to child1\n",getpid());
    fflush(f);

    stat=write(pfd1[1],words,words_len);
    if(stat<0)
    {
        printf("Error writing to second pipe!\n");
        exit(1);
    }



    fprintf(f,"parent pid_%d sent data to child2\n",getpid());
    fflush(f);
    fclose(g);


        if(close(pfd1[1]) == -1)
        {
                printf("Error closing reading end of the pipe.\n");
                exit(EXIT_FAILURE);
        }



    fclose(f);

    wait(NULL);
    return 0;
}


Буду признателен за любое предложение.

РЕДАКТИРОВАТЬ
После внесения некоторых изменений в код с помощью отладчика программа по-прежнему не работает. Когда я запускаю программу, я получаю следующие ошибки:

-bash-4.1$ gcc program.c -o p
-bash-4.1$ ./p 4
Error reding from first pipe
Error reading from second pipe
Error closing reading end of the pipe.

И содержимое файла log.dat следующее:

-bash-4.1$ more log.dat
parent pid_61202 sent data to child1
parent pid_61202 sent data to child2
Third child pid_61205 received data
Third child pid_61205 printed data to file

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