Witaj na Forum Linuxiarzy
Zanim zalogujesz się, by pisać na naszym forum, zapoznaj się z kilkoma zasadami savoir-vivre'u w dziale Administracja.
Wiadomości z problemami zamieszczone w wątku "Przywitaj się" oraz wszelkie reklamy na naszym forum będą usuwane.

Zadanie

Zaczęty przez Kazek, Listopad 19, 2023, 10:15:03 AM

Poprzedni wątek - Następny wątek

Kazek

Witam zacząłem przygodę z linuxem na studiach na których to też dostałem zadanie nad którym pracuję już tydzień. Termin się zbliża a ja odchodzę od zmysłów bo program dalej nie działa:

Wykonaj rodzinę procesów komunikujących się przez potoki, przy czym wszystkie procesy z wyjątkiem "wejściowego" i "wyjściowego" odczytują komunikaty ze wszystkich wejść, składają je w jeden komunikat, dodatkowo wstawiając swój pid i wysyłają go na wszystkie wyjścia.

Proces "wejściowy" (nie mający żadnych potoków wejściowych) inicjuje początkowy ciąg. Proces "wyjściowy" (nie mający żadnych potoków wyjściowych) wypisuje komunikat (złożony z otrzymanych komunikatów z dodanym swoim pid) wynikowy na standardowe wyjście.

Proces pierwotny tworzy strukturę potomków ale nie bierze udziału w komunikacji przez potoki.

Graf to:
Wierzchołek 1 wskazuje na wierzchołki 2 i 3.
Wierzchołek 2 wskazuje na wierzchołek 5.
Wierzchołek 3 wskazuje na wierzchołki 2 i 4.
Wierzchołek 4 wskazuje na wierzchołek 5.

Oraz dostałem taki kod jako przykład:
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include <iostream>
#include <string>
#include <array>
#include <algorithm>

std::string pipeRead(int pipe)
{
std::string message;
char c;
int readed = 0;
while ((readed = read(pipe, &c, 1)) > 0)
message += c;
if (readed == -1)
{
perror("Error reading pipe.");
exit(EXIT_FAILURE);
}
return message;
}

void pipeWrite(int pipe, std::string message)
{
if( write(pipe, message.c_str(), message.length()) == -1)
{
perror("Error writing pipe.");
exit(EXIT_FAILURE);
}
}

std::string pipesRead(std::vector<int> const& pipesIn)
{
std::string message = "{";
message += std::to_string(getpid());
for (auto pipeIn : pipesIn)
{
message += ";";
message += pipeRead(pipeIn);
}
message += "}";
return message;
}


void pipesWrite(std::vector<int> const& pipesOut, std::string message)
{
for (auto pipeOut : pipesOut)
pipeWrite(pipeOut, message);
}

std::vector<std::array<int, 2>> createPipes(int count)
{
std::vector<std::array<int, 2>> pipes;
for (int i = 0; i < count; ++i)
{
std::array<int, 2> newPipe;
if (pipe(newPipe.data()) == -1)
{
perror("Error creating pipe.");
exit(EXIT_FAILURE);
}
pipes.push_back(newPipe);
}
return pipes;
}

int main(int argc, char* argv[])
{
auto pipes = createPipes(2);

if (fork() == 0)
{
// child
close(pipes[0][1]);
close(pipes[1][0]);

std::string message = pipesRead({ pipes[0][0] });
close(pipes[0][0]);

//std::cout << "child read:" << message << "\n";

pipesWrite({ pipes[1][1] }, message);
close(pipes[1][1]);
}
else
{
// parent
close(pipes[0][0]);
close(pipes[1][1]);
std::string message = "{";
message += std::to_string(getpid());
message += "}";

//std::cout << "parent write:" << message << "\n";
pipesWrite({ pipes[0][1] }, message);
close(pipes[0][1]);

message = "";
message = pipesRead({ pipes[1][0] });
close(pipes[1][0]);
//std::cout << "parent read:" << message << "\n";

std::cout << message << "\n";
}
return 0;
}

A to jest to co udało mi się zrobić do tej pory:
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include <iostream>
#include <string>
#include <array>
#include <map>
#include <algorithm>

std::string pipeRead(int pipe) {
    std::string message;
    char c;
    while (read(pipe, &c, 1) > 0)
        message += c;
    return message;
}

void pipeWrite(int pipe, const std::string& message) {
    write(pipe, message.c_str(), message.length());
}

std::vector<std::array<int, 2>> createPipes(int count) {
    std::vector<std::array<int, 2>> pipes;
    for (int i = 0; i < count; ++i) {
        std::array<int, 2> newPipe;
        if (pipe(newPipe.data()) == -1) {
            perror("Error creating pipe.");
            exit(EXIT_FAILURE);
        }
        pipes.push_back(newPipe);
    }
    return pipes;
}

int main() {
    // Mapowanie procesów do ich odpowiednich potoków
    std::map<int, std::vector<int>> processInPipes = {{2, {0}}, {3, {1}}, {4, {3}}, {5, {2, 4}}};
    std::map<int, std::vector<int>> processOutPipes = {{1, {0, 1}}, {2, {2}}, {3, {3}}, {4, {4}}};

    // Tworzenie potoków
    std::vector<std::array<int, 2>> pipes = createPipes(5);

    for (int i = 1; i <= 5; ++i) {
        if (fork() == 0) {
            // Proces potomny
            std::string message = "{PID:" + std::to_string(getpid()) + "}";
            std::vector<int> inPipes = processInPipes[i];
            std::vector<int> outPipes = processOutPipes[i];

            // Zamykanie niepotrzebnych końców potoków
            for (size_t j = 0; j < pipes.size(); ++j) {
                if (std::find(inPipes.begin(), inPipes.end(), static_cast<int>(j)) == inPipes.end()) close(pipes[j][0]);
                if (std::find(outPipes.begin(), outPipes.end(), static_cast<int>(j)) == outPipes.end()) close(pipes[j][1]);
            }

            if (i != 1) {
                // Odczytanie wiadomości z potoków wejściowych
                for (int pipe : inPipes)
                    message += pipeRead(pipes[pipe][0]);
            }

            if (i != 5) {
                // Wysłanie wiadomości do potoków wyjściowych
                for (int pipe : outPipes)
                    pipeWrite(pipes[pipe][1], message);
            } else {
                // Wyświetlenie wiadomości w procesie wyjściowym
                std::cout << message << std::endl;
            }

            exit(0);
        }
    }

    // Proces macierzysty
    for (int i = 0; i < 5; ++i)
        wait(NULL); // Czekanie na zakończenie procesów potomnych

    return 0;
}

Naprawdę próbowałem wiele ale program cały czas się zacina a moja wiedza nie jest jeszcze za wielka bo dopiero się uczę.

Zobacz najnowsze wiadomości na forum