Загрузка данных


#include <cstdlib>
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/wait.h>

void writeToPipe(int fileDescriptor, const std::string& text) {
    std::size_t totalBytesWritten = 0;

    while (totalBytesWritten < text.size()) {
        ssize_t bytesWritten = write(
            fileDescriptor,
            text.data() + totalBytesWritten,
            text.size() - totalBytesWritten
        );

        if (bytesWritten == -1) {
            perror("Ошибка записи в pipe");
            exit(EXIT_FAILURE);
        }

        totalBytesWritten += static_cast<std::size_t>(bytesWritten);
    }
}


std::string readFromPipe(int fileDescriptor) {
    std::string result;
    char buffer[256];

    while (true) {
        ssize_t bytesRead = read(fileDescriptor, buffer, sizeof(buffer));

        if (bytesRead == -1) {
            perror("Ошибка чтения из pipe");
            exit(EXIT_FAILURE);
        }

        if (bytesRead == 0) {
            break;
        }

        result.append(buffer, static_cast<std::size_t>(bytesRead));
    }

    return result;
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Использование: ./sadriev \"строка\"" << std::endl;
        return EXIT_FAILURE;
    }

    int pipe_1[2];

    int pipe_2[2];

    if (pipe(pipe_1) == -1) {
        perror("Ошибка создания pipe_1");
        return EXIT_FAILURE;
    }

    if (pipe(pipe_2) == -1) {
        perror("Ошибка создания pipe_2");
        return EXIT_FAILURE;
    }

    // Создаём дочерний процесс.
    pid_t pid = fork();

    if (pid == -1) {
        perror("Ошибка fork");
        return EXIT_FAILURE;
    }

    if (pid == 0) {
        // ---------------- Дочерний процесс ----------------

        // Дочерний процесс читает из pipe_1.
        close(pipe_1[1]);

        // Дочерний процесс пишет в pipe_2.
        close(pipe_2[0]);

        // Получаем исходную строку от родительского процесса.
        std::string input = readFromPipe(pipe_1[0]);
        close(pipe_1[0]);

        // В дочернем процессе fork() возвращает 0.
        std::cout << "PID CHILD: " << getpid()
                  << "  RETPID: " << pid << std::endl;

        std::string result;

        for (char symbol : input) {
            if (symbol >= '0' && symbol <= '9') {
                result += symbol;
            }
        }

        // Передаём результат родительскому процессу.
        writeToPipe(pipe_2[1], result);
        close(pipe_2[1]);

        _exit(EXIT_SUCCESS);
    }

    // ---------------- Родительский процесс ----------------

    close(pipe_1[0]);

    close(pipe_2[1]);

    std::string input = argv[1];

    std::cout << "PID PARENT: " << getpid()
              << "  RETPID: " << pid << std::endl;

    // Передаём исходную строку дочернему процессу.
    writeToPipe(pipe_1[1], input);
    close(pipe_1[1]);

    // Получаем обработанный результат от дочернего процесса.
    std::string result = readFromPipe(pipe_2[0]);
    close(pipe_2[0]);

    // Ожидаем завершения дочернего процесса.
    waitpid(pid, nullptr, 0);

    std::cout << "Исходная строка: " << input << std::endl;
    std::cout << "Результат: " << result << std::endl;

    return EXIT_SUCCESS;
}