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ę.