Чтение содержимого файла в дочернем процессе и передача его родительскому процессу с использованием канала в C - PullRequest
0 голосов
/ 08 апреля 2020

Мне нужна программа, которая читает файл в дочернем процессе и отправляет строку / содержимое в родительский процесс, используя простой канал.

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

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    FILE * fptr;
    fptr = fopen(argv[1],"r");
    char str1;

    int pipefds[2];
    char buffer[5];

    if(pipe(pipefds) == -1)
    {
        perror("PIPE ERROR");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();

    if(pid == 0)
    {
        char singleLine[150];
        close(pipefds[0]);  
        while(!feof(fptr))
        {
            fgets(singleLine, 150, fptr);
            //puts(singleLine);
            write(pipefds[1], singleLine, sizeof(singleLine));

        }

        fclose(fptr);
                    //Close read file descriptor

        exit(EXIT_SUCCESS);
    }
    else if(pid > 0)
    {
        //wait(NULL);                       //Wait for child process to finish
        close(pipefds[1]);              //Close write file descriptor
        read(pipefds[0], buffer, 100);  //Read pin from pipe
        close(pipefds[0]);              //Close read file descriptor

        printf("%s",buffer);
    }


    return 0;
}

1 Ответ

2 голосов
/ 08 апреля 2020

Проверка аргумента программы

Чтобы убедиться, что указан параметр имени файла, вы можете проверить следующее:

if (argc < 2) {
    fprintf(stderr, "usage: progname <filename>");
    exit(EXIT_FAILURE);
}

Открытие файла

Предположительно, имеет смысл проверить, успешно ли работает fopen.

Вы можете сделать проверку, например, так:

if ((fptr = fopen(argv[1], "r")) == NULL) {
    perror("error opening file");
    exit(EXIT_FAILURE);
}

Также как упомянуто @ В комментариях этот код можно переместить к ребенку.

Чтение файла

Чтение файла можно сделать так:

while (fgets(singleLine, sizeof(singleLine), fptr)) {
    write(pipefds[1], singleLine, strlen(singleLine));
}

Как упоминал Джонатан Леффлер в комментариях, не следует проверять заранее. Также важно отметить, что вы не хотите записывать sizeof (singleLine) байтов, потому что строки могут иметь переменный размер и быть короче размера буфера, поэтому лучше использовать strlen(singleLine) здесь.

Чтение данных

Чтение данных должно происходить в течение всего oop - до тех пор, пока данные доступны. Вызов read возвращает количество прочитанных байтов.

    ssize_t n;
    while ((n = read(pipefds[0], buffer, sizeof(buffer) - 1)) > 0) {
        buffer[n] = '\0';
        printf("%s", buffer);

    }

Чтобы не сохранять данные за пределами буфера, вы можете использовать sizeof(buffer) - 1 в качестве третьего аргумента вызова чтения.

Программа

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

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, char *argv[]) {
    int pipefds[2];
    char buffer[100];

    if (argc < 2) {
        fprintf(stderr, "usage: progname <filename>");
        exit(EXIT_FAILURE);
    }

    if (pipe(pipefds) == -1) {
        perror("PIPE ERROR");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();

    if (pid == 0) {
        FILE *fptr;
        if ((fptr = fopen(argv[1], "r")) == NULL) {
            perror("error opening file");
            exit(EXIT_FAILURE);
        }

        char singleLine[150];
        close(pipefds[0]);
        while (fgets(singleLine, sizeof(singleLine), fptr)) {
            write(pipefds[1], singleLine, strlen(singleLine));
        }
        int error = ferror(fptr);
        fclose(fptr);
        if (error) {
            perror("error reading file");
            exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
    } else if (pid > 0) {
        close(pipefds[1]);

        ssize_t n;
        while ((n = read(pipefds[0], buffer, sizeof(buffer) - 1)) > 0) {
            buffer[n] = '\0';
            printf("%s", buffer);

        }
        close(pipefds[0]);
    }

    return 0;
}
...